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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Drag-n-drop нескольких QGraphicsItem  (Прочитано 9464 раз)
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« : Август 18, 2015, 16:02 »

Давно и успешно работает DnD одного айтема по QGraphicsScene.  Сейчас используется стандартный механизм - в наследнике QGraphicsItem переопределен метод mouseMoveEvent(QGraphicsSceneMouseEvent *event). Внутри него, чтобы начался собственно драг, как рекомендованно в документации, делается

Код:
QDrag* drag = new QDrag( event->widget() );

далее в драг MIME-пакуются нужные данные, приклеивается картинка и собственно начинается drag->exec(). Как положено, если он вернул Qt::IgnoreAction (то есть, бросили в непотребном месте), то айтем возвращается на то место сцены, откуда его драгнули. Всё пучком. Однако пришло время сделать тоже самое для неизвестного заранее числа выделенных айтемов.

И тут пока не совсем ясно - есть вроде бы два пути:
1) Разделить эту функцию на две - одна собственно ловит начало драга, другая его собственно производит. Если выбран более чем один айтем, то в одном из них (который потащили) определяется факт начала драга, а потом для всех выбранных айтемов вызываются функции, производящие собственно драги. У каждого айтема свой драг со своим MIME-пакетом данных. И тогда по идее каждый айтем должен поехать. Но... А могут ли вообще существовать несколько одновременно выполняемых QDrag? Вроде бы эта функциональность реализована средствами ОС, и тут становится еще более не понятно - а все ли хостовые для Qt операционки умеют адекватно таскать несколько MIME-нутых объектов, и умеют ли вообще таскать больше одного?
2) Вроде бы более простой вариант - оставить как есть, но формировать картинку драга из изображения всех подхваченных элементов, в одном месте отрывать их от сцены, запихивать их данные в MIME одного драга, а при падении ронять их из этого майма руками последовательно, один за другим. Что в реализации очевидно будет гораздо более муторно и громоздко, особенно при падении.

Дополнительную сложность представляет то, что сцена не одна - их две, и соответственно группа может перетаскиваться между двумя сценами, либо может быть ошибочно брошена вне любой из сцен.

Кто-нибудь делал мульти-драг нескольких айтемов? Как в общем поступили? Можно общее словесное описание модели, без кода?
Записан

2^7-1 == 127, задумайтесь...
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #1 : Август 18, 2015, 16:30 »

А могут ли вообще существовать несколько одновременно выполняемых QDrag?
Нет.
Записан

Qt 5.11/4.8.7 (X11/Win)
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #2 : Август 18, 2015, 17:13 »

Ну то есть, путь номер 2 только... Там вроде всё понятно, и также понятно, что решение не получится элегантным.  В замешательстве
« Последнее редактирование: Август 18, 2015, 17:16 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Август 18, 2015, 17:23 »

Вариант 1 не достоин обсуждения
2) ...но формировать картинку драга из изображения всех подхваченных элементов..
Именно так делает Qt - и это безобразно (да простят меня фаны, но и на солнце есть пятна). Никому и нафиг не нужна громадная ползающая простыня. Где-то здесь болтается пример, делал DnD строк в таблице. Одна строка - один листик. Две строки - два. Три и более - три листика, все, больше наращивать drag image нет смысла. Общий размер "таскаемого" не больше 100 пыкселей. "Use metaphor" как учит "Human Interface.."  
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #4 : Август 18, 2015, 17:36 »

Именно так делает Qt

где он так делает?

- и это безобразно (да простят меня фаны, но и на солнце есть пятна). Никому и нафиг не нужна громадная ползающая простыня.

смотря что именно таскается... в случае схемы из множества элементов, реально пользователь будет таскать только несколько лежащих рядом друг с другом - на предмет освобождения пространства, или для красоты размещения

ну и, наконец, если самому изображение формировать, ничто не мешает "растворить" его края, и даже сделать пользовательскую настройку размеров таскаемого изображения
Записан

2^7-1 == 127, задумайтесь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Август 18, 2015, 18:09 »

где он так делает?
Та везде, QTableWidget, QTreeWidget и.т.п. Попробуйте выбрать много айтемов и тащить.. (можно просто в дызайнере). Неужели нравится?  Улыбающийся

смотря что именно таскается... в случае схемы из множества элементов, реально пользователь будет таскать только несколько лежащих рядом друг с другом - на предмет освобождения пространства, или для красоты размещения

ну и, наконец, если самому изображение формировать, ничто не мешает "растворить" его края, и даже сделать пользовательскую настройку размеров таскаемого изображения
Забейте на это и сделайте "абстрактный" таскаемый имедж - так намного и лучше и дешевле.

Что касается самих данных. Корректный, академический подход - драг сам содержит все что драгается. Даже если источник уже удален - дроп должен сработать. Часто это сводится к сериализации в том или ином виде. Не всегда так удобно делать - часто куда легче проскочить напр используя selection источника. В любом случае - откуда проблемы? Ну дропнули 2 (или 10, 100) вместо только одного, в чем (принципиальные) сложности-то?
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #6 : Август 18, 2015, 18:59 »

Та везде, QTableWidget, QTreeWidget и.т.п. Попробуйте выбрать много айтемов и тащить.. (можно просто в дызайнере). Неужели нравится?  Улыбающийся

Не знаю, не пробовал.

Забейте на это и сделайте "абстрактный" таскаемый имедж - так намного и лучше и дешевле.

Нет, так не пойдет. У меня схема, и пользователь перетаскивает элементы схемы, которые могут иметь самые разные изображения, сейчас я просто беру текущее изображение элемента, и его делаю битмапом, подгоняю курсор под позицию начала. Выглядит очень естественно - лежит на схеме элемент, его взяли и перенесли. Если выделяется много элементов, их тоже надо взять и перенести. Можно при переносе действительно не рисовать все элементы (циркулярный градиент прозрачности на изображение драга наложить), но пользователь должен видеть что именно и куда он тащит.

Что касается самих данных. Корректный, академический подход - драг сам содержит все что драгается. Даже если источник уже удален - дроп должен сработать. Часто это сводится к сериализации в том или ином виде. Не всегда так удобно делать - часто куда легче проскочить напр используя selection источника. В любом случае - откуда проблемы? Ну дропнули 2 (или 10, 100) вместо только одного, в чем (принципиальные) сложности-то?

Таскаемые объекты у меня в принципе не могут быть удалены во время драга (только при завершении приложения). Но внутреннее состояние объектов может измениться во время драга (в любом объекте даже во время драга может работать нить, или он может сигнал получить), и упасть должен изменённый консистентный объект, а не тот, который начинали тащить. Если точнее - то у меня таскают и роняют не сам объект, а только его изображение на схеме. Поэтому вместо сериализованного объекта, драг у меня содержит просто указатель на объект. Теперь вместо одного указателя надо запихивать в драг массив указателей при начале переноса, и при падении соответственно доставать все указатели и ронять все объекты, причём каждый в его относительную позицию от начала драга - чтобы они попадали относительно друг друга примерно так же, как их со схемы подняли. Придётся эти относительные позиции тоже вместе с указателями в драг запихивать, поскольку одной только позиции самого дропа теперь недостаточно, у каждого объекта будет своя позиция дропа. Логических сложностей вроде бы нет, просто заметно больше придётся добавить кода. Вручную всё, ибо увы, в Qt мульти-драг никак не поддерживается на нижнем уровне.
« Последнее редактирование: Август 18, 2015, 19:01 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Август 18, 2015, 19:37 »

Нет, так не пойдет. У меня схема, ...
Не "пойдет". а "полетит" - нужно только отказаться от предрассудков засевших в наших головах (да, это трудно, мы всегда переоцениваем собственный опыт)

Таскаемые объекты у меня в принципе не могут быть удалены во время драга (только при завершении приложения). Но внутреннее состояние объектов может измениться во время драга (в любом объекте даже во время драга может работать нить, или он может сигнал получить), и упасть должен изменённый консистентный объект, а не тот, который начинали тащить. Если точнее - то у меня таскают и роняют не сам объект, а только его изображение на схеме. Поэтому вместо сериализованного объекта, драг у меня содержит просто указатель на объект. Теперь вместо одного указателя надо запихивать в драг массив указателей при начале переноса, и при падении соответственно доставать все указатели и ронять все объекты, причём каждый в его относительную позицию от начала драга - чтобы они попадали относительно друг друга примерно так же, как их со схемы подняли. Придётся эти относительные позиции тоже вместе с указателями в драг запихивать, поскольку одной только позиции самого дропа теперь недостаточно, у каждого объекта будет своя позиция дропа. Логических сложностей вроде бы нет,
Ну это глухая специфика задачи - надо так надо. Случай очень редкий - обычно принимающему все равно "как были выбраны" - то ли это айтемы (0, 1, 2) то ли (100, 200, 300) - его дело "принять" и обычно "подряд". Что-то мутить с позицией - ой вряд ли

просто заметно больше придётся добавить кода. Вручную всё, ибо увы, в Qt мульти-драг никак не поддерживается на нижнем уровне.
Вы уж меня извините, но просто неудобно (и обидно) слышать такой "поросячий визг" от человека примерно моего возраста. Хуже молодого, "ах, попку не подмыли" - ничего, сами подмоетесь
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #8 : Август 18, 2015, 20:13 »

Ну это глухая специфика задачи - надо так надо. Случай очень редкий - обычно принимающему все равно "как были выбраны" - то ли это айтемы (0, 1, 2) то ли (100, 200, 300) - его дело "принять" и обычно "подряд". Что-то мутить с позицией - ой вряд ли

Не вряд ли, а точно. Чтобы было понятнее о чем речь - c рисовалками блочных диаграмм типа Visio или чем-то аналогичным (OpenOffice Draw) приходилось иметь дело? Вот аналогично нарисована схема, выделяются на ней несколько элементов с зажатой кнопкой Ctrl, и перетаскиваются в другое место схемы. При этом взаимное расположение элементов не меняется, то есть, координаты каждого учитывать надо. Совсем не редкий случай.

Вы уж меня извините, но просто неудобно (и обидно) слышать такой "поросячий визг" от человека примерно моего возраста. Хуже молодого, "ах, попку не подмыли" - ничего, сами подмоетесь

Не нашел никакого "поросячьего визга", это глупость какая-то. Есть констатация факта - мульти-драг довольно востребованная операция, которая в Qt никак не поддерживается. Хотя решение, на самом деле, получится типовое, вполне могло бы быть библиотечным.
« Последнее редактирование: Август 18, 2015, 20:24 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #9 : Август 18, 2015, 21:20 »

Ну то есть, путь номер 2 только... Там вроде всё понятно, и также понятно, что решение не получится элегантным.  В замешательстве
Только это и остается.
Судя по описанию вы undo-стек не реализовывали? В данном случае вы бы использовали его механизмы для удаления/вставки и промежуточного хранения объектов.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #10 : Август 18, 2015, 21:34 »

Ну то есть, путь номер 2 только... Там вроде всё понятно, и также понятно, что решение не получится элегантным.  В замешательстве
Только это и остается.
Судя по описанию вы undo-стек не реализовывали? В данном случае вы бы использовали его механизмы для удаления/вставки и промежуточного хранения объектов.

нет, но в планах, с начала не было очевидно, как его делать, поскольку не было очевидно, какие объекты как будут работать, сейчас основное реализовано, и undo-redo более-менее просматривается
Записан

2^7-1 == 127, задумайтесь...
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #11 : Август 18, 2015, 21:41 »

нет, но в планах, с начала не было очевидно, как его делать, поскольку не было очевидно, какие объекты как будут работать, сейчас основное реализовано, и undo-redo более-менее просматривается
Ну раз оно уже просматривается, то должны просматриваться контейнеры для объектов, в которые они будут помещаться при удалении, для того, что бы была возможность при redo их восстановить. Т.е. для этого (так же как и для перетаскивания) понадобятся операции удалить со сцены объекты в промежуточный контейнер и вернуть на сцену объекты из промежуточного контейнера. С помощью них перетаскивание сведется к удалению и вставке в новое место (или в старое если перетаскивание отменили).
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #12 : Август 18, 2015, 22:52 »

нет, но в планах, с начала не было очевидно, как его делать, поскольку не было очевидно, какие объекты как будут работать, сейчас основное реализовано, и undo-redo более-менее просматривается
Ну раз оно уже просматривается, то должны просматриваться контейнеры для объектов, в которые они будут помещаться при удалении, для того, что бы была возможность при redo их восстановить. Т.е. для этого (так же как и для перетаскивания) понадобятся операции удалить со сцены объекты в промежуточный контейнер и вернуть на сцену объекты из промежуточного контейнера. С помощью них перетаскивание сведется к удалению и вставке в новое место (или в старое если перетаскивание отменили).

Нет, тут всё не так... в подробности нет смысла вдаваться, но никакие контейнеры в моём случае не нужны. Перетаскивание по одному объекту и так давным давно работает, надо сделать на его основе перетаскивание многих. Как делать, ясно, но переделка получается не в десять строк.
Записан

2^7-1 == 127, задумайтесь...
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #13 : Август 18, 2015, 23:00 »

Я не на чем не настаиваю. Улыбающийся
Просто если undo-стек в планах, то реализуйте перетаскивание с видами на него. Что бы функции используемые для перетаскивании в дальнейшем можно было использовать для реализации других операций, как то групповое удаление объектов со сцены и откат этой операции (и наоборот).
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #14 : Август 18, 2015, 23:08 »

Я не на чем не настаиваю. Улыбающийся
Просто если undo-стек в планах, то реализуйте перетаскивание с видами на него. Что бы функции используемые для перетаскивании в дальнейшем можно было использовать для реализации других операций, как то групповое удаление объектов со сцены и откат этой операции (и наоборот).

Вот фишка в том, что те объекты, которые перетаскиваются, никогда не удаляются, а те, которые удаляются, никогда не перетаскиваются.  Смеющийся
Записан

2^7-1 == 127, задумайтесь...
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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