Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: alexman от Ноябрь 12, 2010, 13:31



Название: Drag&Drop - не работает перестановка двух элементов по dropEvent.
Отправлено: alexman от Ноябрь 12, 2010, 13:31
Наследуюсь от QTreeWidget и переопределяю dragMoveEvent, dropEvent. Проблема заключается в том, что механизм перестановки двух элементов в dropEvent не работает. Если точнее, то элемент по takeTopLevelItem удаляется, но не вставляется по insertTopLevelItem. Что не так делаю?

Вот код:
Код:
#include <QtCore/QDebug>
#include <QtGui/QApplication>
#include <QtGui/QDragMoveEvent>
#include <QtGui/QPainter>
#include <QtGui/QTreeWidget>

class TreeWidget : public QTreeWidget
{
public:
TreeWidget( QWidget* parent = 0 )
: QTreeWidget( parent ),
_dragMoveItemBelow( 0 )
{
setDragDropMode( QTreeWidget::InternalMove );
}

~TreeWidget() {}

private:
void dragMoveEvent( QDragMoveEvent* event )
{
_dragMoveLine = QLine();
event->ignore();

QTreeWidgetItem* item = itemFromIndex( indexAt( event->pos() ) );
if ( item == currentItem() ) {
return;
}

const QRect& rect = visualRect( indexAt( event->pos() ) );
if ( rect.top() + 2 >= event->pos().y() ) {
if ( currentItem() == itemAbove( item ) ) {
return;
}

_dragMoveLine = QLine( rect.left(), rect.top(), rect.right(), rect.top() );
_dragMoveItemBelow = item;
event->acceptProposedAction();
} else if ( rect.bottom() - 2 <= event->pos().y() ) {
if ( currentItem() == itemBelow( item ) ) {
return;
}

_dragMoveLine = QLine( rect.left(), rect.bottom(), rect.right(), rect.bottom() );
_dragMoveItemBelow = itemBelow( item );
event->acceptProposedAction();
}

viewport()->update();
}

void dropEvent( QDropEvent* )
{
QTreeWidgetItem* item = currentItem();
item = takeTopLevelItem( indexOfTopLevelItem( item ) );

insertTopLevelItem( indexOfTopLevelItem( _dragMoveItemBelow ), item );
setCurrentItem( item );

_dragMoveLine = QLine();
viewport()->update();
}

void paintEvent( QPaintEvent* event )
{
QTreeWidget::paintEvent( event );

QPainter p( viewport() );
p.setPen( QPen( Qt::black, 2 ) );
p.drawLine( _dragMoveLine );
}

QLine _dragMoveLine;
QTreeWidgetItem* _dragMoveItemBelow;
};

int main( int argc, char** argv )
{
QApplication app( argc, argv );

TreeWidget widget;
widget.setColumnCount( 1 );
widget.headerItem()->setText( 0, QObject::tr( "Title" ) );

QTreeWidgetItem* item1 = new QTreeWidgetItem( &widget );
item1->setText( 0, "1" );

QTreeWidgetItem* item2 = new QTreeWidgetItem( &widget );
item2->setText( 0, "2" );

QTreeWidgetItem* item3 = new QTreeWidgetItem( &widget );
item3->setText( 0, "3" );

QTreeWidgetItem* item4 = new QTreeWidgetItem( &widget );
item4->setText( 0, "4" );

QTreeWidgetItem* item5 = new QTreeWidgetItem( &widget );
item5->setText( 0, "5" );

app.setActiveWindow( &widget );
widget.show();

return app.exec();
}


Название: Re: Drag&Drop - не работает перестановка двух элементов по dropEvent.
Отправлено: GreatSnake от Ноябрь 12, 2010, 13:42
в начале dropEvent() нужно вставить:

if( _dragMoveItemBelow == currentItem() )
  return;

+
если кидаете в конец дерева, то нужно использовать QTreeWidget::addTopLevelItem().


Название: Re: Drag&Drop - не работает перестановка двух элементов по dropEvent.
Отправлено: alexman от Ноябрь 12, 2010, 14:03
если кидаете в конец дерева, то нужно использовать QTreeWidget::addTopLevelItem().
С этим понятно.

в начале dropEvent() нужно вставить:

if( _dragMoveItemBelow == currentItem() )
  return;
Данный случай невозможен!

Вопрос открыт!


Название: Re: Drag&Drop - не работает перестановка двух элементов по dropEvent.
Отправлено: alexman от Ноябрь 12, 2010, 14:10
Кстати addTopLevelItem тоже не отрабатывает корректно!


Название: Re: Drag&Drop - не работает перестановка двух элементов по dropEvent.
Отправлено: GreatSnake от Ноябрь 12, 2010, 14:13
ну тогда:

if( !_dragMoveItemBelow )
  return;

В общем не поленился собрал пример - всё правильно работает, за исключением если кидать в начало и в конец.


Название: Re: Drag&Drop - не работает перестановка двух элементов по dropEvent.
Отправлено: GreatSnake от Ноябрь 12, 2010, 14:15
Цитировать
Кстати addTopLevelItem тоже не отрабатывает корректно!
Правильно, потому что dragMoveItemBelow в этом случае всегда будет 0 )
Вообще-то, мог бы и сам догадаться )


Название: Re: Drag&Drop - не работает перестановка двух элементов по dropEvent.
Отправлено: alexman от Ноябрь 12, 2010, 14:28
Цитировать
Кстати addTopLevelItem тоже не отрабатывает корректно!
Правильно, потому что dragMoveItemBelow в этом случае всегда будет 0 )
Вообще-то, мог бы и сам догадаться )
Да это не готовый пример! Все нюансы не были учтены! У меня на машине не работает, например, если взять 0-ой элемент и перетащить на место 1-ого. Вот в этом проблема! У вас это работает?


Название: Re: Drag&Drop - не работает перестановка двух элементов по dropEvent.
Отправлено: alexman от Ноябрь 12, 2010, 14:30
Вот новый dropEvent:
Код:
void dropEvent( QDropEvent* )
{
QTreeWidgetItem* item = currentItem();
item = takeTopLevelItem( indexOfTopLevelItem( item ) );

if ( _dragMoveItemBelow ) {
insertTopLevelItem( indexOfTopLevelItem( _dragMoveItemBelow ), item );
} else {
addTopLevelItem( item );
}

setCurrentItem( item );

_dragMoveLine = QLine();
viewport()->update();
}


Название: Re: Drag&Drop - не работает перестановка двух элементов по dropEvent.
Отправлено: GreatSnake от Ноябрь 12, 2010, 14:34
Работает.
И не учтён ещё момент перемещения в начало.


Название: Re: Drag&Drop - не работает перестановка двух элементов по dropEvent.
Отправлено: alexman от Ноябрь 12, 2010, 14:37
Можете свой код с исправленияси запостить? Так как у меня описанный случай не работает!


Название: Re: Drag&Drop - не работает перестановка двух элементов по dropEvent.
Отправлено: GreatSnake от Ноябрь 12, 2010, 14:58
Цитировать
Можете свой код с исправленияси запостить? Так как у меня описанный случай не работает!
А смысл? Я ничего своего не вносил. Всё ваше.
Проверил на linux-e  Qt 4.5, 4.6.2, 4.7.1 - везде всё ok.

Цитировать
И не учтён ещё момент перемещения в начало.
Упс, погорячился - всё работает.


Название: Re: Drag&Drop - не работает перестановка двух элементов по dropEvent.
Отправлено: alexman от Ноябрь 12, 2010, 15:08
Под виндой (windows xp, qt 4.6.2, 4.7.0, 4.7.1) не работает! Есть винда?


Название: Re: Drag&Drop - не работает перестановка двух элементов по dropEvent.
Отправлено: alexman от Ноябрь 12, 2010, 15:55
Поблема решена! Спасибо за ответы!
Необходимо заменить setDragDropMode( QTreeWidget::InternalMove ); на setDragDropMode( QTreeWidget::DragDrop ); Видимо при включеном режиме InternalMove запрещается вставлять элементы!


Название: Re: Drag&Drop - не работает перестановка двух элементов по dropEvent.
Отправлено: GreatSnake от Ноябрь 12, 2010, 15:55
Цитировать
Под виндой (windows xp, qt 4.6.2, 4.7.0, 4.7.1) не работает! Есть винда?
Мде, WS2003 Qt4.7.1 тоже не работает!


Название: Re: Drag&Drop - не работает перестановка двух элементов по dropEvent.
Отправлено: GreatSnake от Ноябрь 12, 2010, 16:04
Цитировать
Поблема решена! Спасибо за ответы!
Необходимо заменить setDragDropMode( QTreeWidget::InternalMove ); на setDragDropMode( QTreeWidget::DragDrop ); Видимо при включеном режиме InternalMove запрещается вставлять элементы!
Ну это же баг. Коли в руководстве не оговаривается про другое повидение на винде, то и работать должно одинаково.
Так что вперёд на bugreports.qt.nokia.com! (http://bugreports.qt.nokia.com!)


Название: Re: Drag&Drop - не работает перестановка двух элементов по dropEvent.
Отправлено: alexman от Ноябрь 13, 2010, 23:21
Цитировать
Поблема решена! Спасибо за ответы!
Необходимо заменить setDragDropMode( QTreeWidget::InternalMove ); на setDragDropMode( QTreeWidget::DragDrop ); Видимо при включеном режиме InternalMove запрещается вставлять элементы!
Ну это же баг. Коли в руководстве не оговаривается про другое повидение на винде, то и работать должно одинаково.
Так что вперёд на bugreports.qt.nokia.com! (http://bugreports.qt.nokia.com!)
Возможно баг под linux?  ;)