Russian Qt Forum
Апрель 27, 2024, 07:37 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Drag&Drop - не работает перестановка двух элементов по dropEvent.  (Прочитано 9792 раз)
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();
}
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #1 : Ноябрь 12, 2010, 13:42 »

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

if( _dragMoveItemBelow == currentItem() )
  return;

+
если кидаете в конец дерева, то нужно использовать QTreeWidget::addTopLevelItem().
« Последнее редактирование: Ноябрь 12, 2010, 13:45 от GreatSnake » Записан

Qt 5.11/4.8.7 (X11/Win)
alexman
Гость
« Ответ #2 : Ноябрь 12, 2010, 14:03 »

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

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

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

Вопрос открыт!
Записан
alexman
Гость
« Ответ #3 : Ноябрь 12, 2010, 14:10 »

Кстати addTopLevelItem тоже не отрабатывает корректно!
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #4 : Ноябрь 12, 2010, 14:13 »

ну тогда:

if( !_dragMoveItemBelow )
  return;

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

Qt 5.11/4.8.7 (X11/Win)
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #5 : Ноябрь 12, 2010, 14:15 »

Цитировать
Кстати addTopLevelItem тоже не отрабатывает корректно!
Правильно, потому что dragMoveItemBelow в этом случае всегда будет 0 )
Вообще-то, мог бы и сам догадаться )
Записан

Qt 5.11/4.8.7 (X11/Win)
alexman
Гость
« Ответ #6 : Ноябрь 12, 2010, 14:28 »

Цитировать
Кстати addTopLevelItem тоже не отрабатывает корректно!
Правильно, потому что dragMoveItemBelow в этом случае всегда будет 0 )
Вообще-то, мог бы и сам догадаться )
Да это не готовый пример! Все нюансы не были учтены! У меня на машине не работает, например, если взять 0-ой элемент и перетащить на место 1-ого. Вот в этом проблема! У вас это работает?
Записан
alexman
Гость
« Ответ #7 : Ноябрь 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();
}
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #8 : Ноябрь 12, 2010, 14:34 »

Работает.
И не учтён ещё момент перемещения в начало.
Записан

Qt 5.11/4.8.7 (X11/Win)
alexman
Гость
« Ответ #9 : Ноябрь 12, 2010, 14:37 »

Можете свой код с исправленияси запостить? Так как у меня описанный случай не работает!
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #10 : Ноябрь 12, 2010, 14:58 »

Цитировать
Можете свой код с исправленияси запостить? Так как у меня описанный случай не работает!
А смысл? Я ничего своего не вносил. Всё ваше.
Проверил на linux-e  Qt 4.5, 4.6.2, 4.7.1 - везде всё ok.

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

Qt 5.11/4.8.7 (X11/Win)
alexman
Гость
« Ответ #11 : Ноябрь 12, 2010, 15:08 »

Под виндой (windows xp, qt 4.6.2, 4.7.0, 4.7.1) не работает! Есть винда?
Записан
alexman
Гость
« Ответ #12 : Ноябрь 12, 2010, 15:55 »

Поблема решена! Спасибо за ответы!
Необходимо заменить setDragDropMode( QTreeWidget::InternalMove ); на setDragDropMode( QTreeWidget::DragDrop ); Видимо при включеном режиме InternalMove запрещается вставлять элементы!
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #13 : Ноябрь 12, 2010, 15:55 »

Цитировать
Под виндой (windows xp, qt 4.6.2, 4.7.0, 4.7.1) не работает! Есть винда?
Мде, WS2003 Qt4.7.1 тоже не работает!
Записан

Qt 5.11/4.8.7 (X11/Win)
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #14 : Ноябрь 12, 2010, 16:04 »

Цитировать
Поблема решена! Спасибо за ответы!
Необходимо заменить setDragDropMode( QTreeWidget::InternalMove ); на setDragDropMode( QTreeWidget::DragDrop ); Видимо при включеном режиме InternalMove запрещается вставлять элементы!
Ну это же баг. Коли в руководстве не оговаривается про другое повидение на винде, то и работать должно одинаково.
Так что вперёд на bugreports.qt.nokia.com!
Записан

Qt 5.11/4.8.7 (X11/Win)
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.072 секунд. Запросов: 22.