Название: (РЕШЕНО) QDrag по сетке Отправлено: Гурман от Февраль 09, 2015, 12:53 3 года назад достаточно было перетаскивать айтемы между двумя сценами и виджетом. Это было сразу сделано с использованием QDrag, и нормально работало. Сейчас понадобилось в одной из сцен (назовем ее холст) иметь сетку (grid) - если драг переносится на холсте, или перетаскивается на холст из другой сцены (назовем её палитра), то над холстом он должен двигаться по узлам сетки. При выходе из холста айтем должен двигаться свободно, и роняться в палитру или третий виджет (назовем его мусорник). После изучения документации не видно никакой возможности управлять координатами события QGraphicsSceneDragDropEvent, которое принимает холст. Получить можно, проверить на попадание в узел сетки можно, но принудительно перемещать - не видно как.
Переделывать QDrag в перетаскивание простых QGraphicsItem по холсту (так рекомендуют делать простую сетку) очень не хочется. Возможность перетаскивания с холста в мусорник, с холста в палитру и с палитры на холст должна не измениться. То есть, придется еще мостырить преобразование перемещения айтемов в QDrag при выходе из с холста, и обратное преобразование QDrag в перемещение айтемов при входе в холст. Бутерброд получится слишком неуклюжий. Может я что-то упускаю? Кто-нибудь делал похожее? Может ли как-нибудь помочь класс QGraphicsGridLayout? Насколько я понимаю, он предназначен для автоматической компоновки элементов управления на диалогах, которые создаются динамически. Не вижу, можно ли его применить для реализации сетки, если да, то как. Название: Re: QDrag по сетке Отправлено: Bepec от Февраль 09, 2015, 13:17 Получаете координаты драга, при попадании на сетку перемещаете курсор к ближайщей точке привязки. Драг соответственно пойдёт туда же.
Разве нет? Название: Re: QDrag по сетке Отправлено: Гурман от Февраль 09, 2015, 13:36 Не, проблема есть. QCursor::setPos() перемещает в координатах экрана. Чтобы получить координаты экрана, надо преобразовать в них координаты QWidget. Но QGraphicsScene не наследует из QWidget. А я получаю в событии QGraphicsSceneDragDropEvent значения в системе координат QGraphicsScene. Не могу пересчитать их в реальные координаты экрана. Теоретически, можно бы посчитать сетку только для курсора, когда он находится над холстом. Но это будет косяк из косяков - сетка будет перемещаться по холсту при изменении его положения внутри окна. Холст то огромного размера...
Кстати, даже если бы можно было пересчитать координаты, всё равно косяк бы получился. Рядом с рамками холста курсор бы скакал, вместо того, чтобы просто отрываться. Название: Re: QDrag по сетке Отправлено: Bepec от Февраль 09, 2015, 13:47 Плавность перемещения это другая проблема. Что вполне решается начальной привязкой к одной ячейке и плавным переходом к другим узлам.
А координаты пересчитываться должны как то, хотя я не задавался этим вопросом. Название: Re: QDrag по сетке Отправлено: Гурман от Февраль 09, 2015, 14:15 Разные системы координат - есть виджет, в котором окно. У него своя система координат. Сцена перемещается внутри этого окна, у неё своя система координат, и она перемещается относительно виджета. Мне нужно привязываться к координатам на сцене, а не к виджету. Пересчета координат сцены в координаты виджета, в котором отображается сцена, я не вижу.
Плавность не волнует пока. Скачки были бы при перемещении курсора от точек привязки, наиболее близких к границам окна. От них курсор выпрыгывал бы сразу за границу, математически на следующую точку привязки, но она уже не видна, находится под рамкой. И дальность выпрыгивания зависела бы от того, как близко точка привязки находится к границе окна. Весьма неадекватное было бы поведение. Название: Re: QDrag по сетке Отправлено: Bepec от Февраль 09, 2015, 14:31 Насчёт пересчёта координат - подумайте, поищите варианты. Я близко не работал со сценой, тут не подскажу.
Насчёт "выпрыгиваний" - это бред. Всё решается просто, буквально надо написать поведения для 5-7 случаев. И будет у вас плавное не скачущее поведение. Название: Re: QDrag по сетке Отправлено: Igors от Февраль 09, 2015, 14:40 Не уверен что прыгающий/прилипающий курсор - то что нужно. Может лучше сделать drag полурозрачным, а самому подсвечивать точку привязки
Название: Re: QDrag по сетке Отправлено: Гурман от Февраль 09, 2015, 15:10 Не уверен что прыгающий/прилипающий курсор - то что нужно. Может лучше сделать drag полурозрачным, а самому подсвечивать точку привязки Нет, когда драг попадает в холст, нужен именно прилипающий драг. Также, как во многих граф. редакторах. Теоретически, можно было бы сделать приклеивание к сетке при дропе - но меня лично такой вариант всегда раздражал. Когда тащишь объект по сетке шагами, то ясно, где он останется. А когда бросаешь, а он прилипает немного в сторону, это злит. Название: Re: QDrag по сетке Отправлено: Гурман от Февраль 09, 2015, 23:05 Можно пересчитать координаты сообытия на сцене в координаты курсора.
QCursor::setPos( views().at(0)->mapToGlobal( views().at(0)->mapFromScene( event->scenePos() ) ) ); Иногда Qt мне не нравится... Название: Re: QDrag по сетке Отправлено: Bepec от Февраль 10, 2015, 02:15 Никто не идеален, ничто не идеально...
Название: Re: QDrag по сетке Отправлено: GreatSnake от Февраль 10, 2015, 12:22 Нет, когда драг попадает в холст, нужен именно прилипающий драг. Средствами QDrag такое не реализуешь.Мало того, drag'n'drop используется нативный со своими заморочками Цитата: assistant Note: On Linux and Mac OS X, the drag and drop operation can take some time, but this function does not block the event loop. Other events are still delivered to the application while the operation is performed. On Windows, the Qt event loop is blocked while during the operation. Например, на винде не получится в процессе драга поменять иконку. Может и курсор сдвинуть тоже, не проверял (по мне, так это будет просто издевательство над юзером).Цитировать Также, как во многих граф. редакторах. Там не используется нативный d'n'd.Название: Re: QDrag по сетке Отправлено: Гурман от Февраль 10, 2015, 13:59 Средствами QDrag такое не реализуешь. На самом деле, почти реализовал. Верес прав насчет перемещения драга за системным курсором. Если изменять QCursor::setPos() то курсор перемещается, и драг вместе с ним. Предложенный Вересом вариант почти работает, драг прилипает к координатам сетки, я их просто арифметически вычисляю при перемещении в методе QGraphicsScene::dragMoveEvent(...) и перевожу в координаты системного курсора. Единственное что пока не поборол - курсор продолжает перемещаться за системной мышью, в результате драг "сопротивляется". Когда мышь двигаешь - он сначала подрагивает в нужном направлении (отрывается, чуть перемещается, потом приклеивается обратно). Потом перепрыгивает на ближайшую точку сетки в нужном направлении. Это не юзабельно, надо что-то придумать, как-то отключить системное перемещение курсора за мышью. Разумеется, при этом не потеряв переносимость. Название: Re: QDrag по сетке Отправлено: GreatSnake от Февраль 10, 2015, 14:16 Это не юзабельно, надо что-то придумать, как-то отключить системное перемещение курсора за мышью. Разумеется, при этом не потеряв переносимость. Я же вроде объяснил, что это не реализуемо.Название: Re: QDrag по сетке Отправлено: Bepec от Февраль 10, 2015, 14:45 Не особо понял проблему, если распишите поподробнее (пойдёт и гифка допустим), можно будет подумать.
to GreatSnake: мне сотни раз говорили эту фразу. Единственный вывод, который я из неё вынес - нет не реализуемого, есть труднореализуемое. Название: Re: QDrag по сетке Отправлено: Гурман от Февраль 10, 2015, 15:07 Не особо понял проблему, если распишите поподробнее (пойдёт и гифка допустим), можно будет подумать. Да лучше уже не описать. Могу только повторить. Курсор реагирует на физические перемещения мыши, он двигается в соответствии с ними. Как обычно двигается. Но я его еще и принуждаю устанавливаться в точки сетки - он устанавливается. Результат выглядит так - если медленно везти мышь, драг просто дергается на месте возле своего узла. Если интенсивнее, то он подергивается, но при этом перепрыгивает по узлам. Но не подряд по узлам сетки, а рывками, перескакивая несколько узлов. Это потому, что на драг влияют не только мои команды установки setPos(), но и системные перемещения мыши. Я ведь получаю в QGraphicsSceneDragDropEvent координаты после того, как курсор прилип к узлу сетки. А чтобы перемещать мышь отдельно, а курсор отдельно, надо получать в событии координаты мыши, как если бы сетки не было. То есть, нужно еще перехватывать тики мыши, делать "виртуальный курсор", который ничего не знает про сетку, и его координаты использовать в качестве исходных. То есть, разделить экранный курсор и перемещение мыши. Название: Re: QDrag по сетке Отправлено: GreatSnake от Февраль 10, 2015, 15:21 to GreatSnake: мне сотни раз говорили эту фразу. Единственный вывод, который я из неё вынес - нет не реализуемого, есть труднореализуемое. Ну, давай переделай приватный QDragManager ;DНазвание: Re: QDrag по сетке Отправлено: Bepec от Февраль 10, 2015, 15:26 ммм.
Ну вроде попонятнее стало мне. Так то виртуальный курсор конечно самый первый пришедший на ум выход - отрисовывать что угодно и где угодно, отсеивая рывки мышки. Я так понимаю задача - чтобы картинка при драге прилипала, а курсор двигался плавно, получается? Тогда действительно проще сделать виртуалку в виде pixmap'а летающего по сетке за курсором. PS а исходники того, что уже получилось не выложите? Интересно поизучать будет, да и вдруг подобное придётся делать. PPS и приватный переделывается) Покупается куте коммерческое и переделывается всё что хотите. (хотя я сейчас не уверен, кто то писал что и в халявной версии можно). Название: Re: QDrag по сетке Отправлено: GreatSnake от Февраль 10, 2015, 15:33 PPS и приватный переделывается) Покупается куте коммерческое и переделывается всё что хотите. (хотя я сейчас не уверен, кто то писал что и в халявной версии можно). Глупость. Путь в никуда.2ТС: коли нужна такая фича, откажись от QDrag и сам таскай айтемы. Название: Re: QDrag по сетке Отправлено: Гурман от Февраль 10, 2015, 15:40 Я так понимаю задача - чтобы картинка при драге прилипала, а курсор двигался плавно, получается? Нет, не совсем. Драгом я называю курсор+картинка, образовавшиеся после вызова drag->exec(). Достаточно, чтобы это всё вместе перемещалось по сетке. Когда драга нет, обычный курсор двигается плавно. А исходников каких-то нет особенных. Есть у меня MainScene, унаследованная от QGraphicsScene, на которой всё это происходит, и у нее переопределен один виртуальный метод Код: void MainScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event) И всё, собственно... сам драг сделан стандартным способом по документации, он не изменился. Название: Re: QDrag по сетке Отправлено: Гурман от Февраль 10, 2015, 15:42 коли нужна такая фича, откажись от QDrag и сам таскай айтемы. Описывал уже в начале, почему это не годится. Такой галимый макдональдс получится, что заранее тошно. Название: Re: QDrag по сетке Отправлено: Гурман от Февраль 10, 2015, 15:53 Тогда действительно проще сделать виртуалку в виде pixmap'а летающего по сетке за курсором. Пока не видно, как это вообще сделать. Надо полностью перехватить перемещения мыши при выполнении драга, чтобы системный курсор не двигался. Но при этом умудриться выдавать событие QGraphicsSceneDragDropEvent в сцену. Или может сигналы посылать... пока в раздумьях.... Проблема в том, что при вытаскивании этого драга за сцену, он должен начинать работать без всяких фокусов. А при втаскивании обратно - снова цепляться за сетку. Название: Re: QDrag по сетке Отправлено: GreatSnake от Февраль 10, 2015, 16:34 Описывал уже в начале, почему это не годится. Такой галимый макдональдс получится, что заранее тошно. Можно попробовать замиксить - QDrag для внешних окон и двигание айтема на сцене.Название: Re: QDrag по сетке Отправлено: Гурман от Февраль 10, 2015, 16:42 Описывал уже в начале, почему это не годится. Такой галимый макдональдс получится, что заранее тошно. Можно попробовать замиксить - QDrag для внешних окон и двигание айтема на сцене.Вот это и будет кошмарный гамбургер... Название: Re: QDrag по сетке Отправлено: Igors от Февраль 11, 2015, 10:01 Пока не видно, как это вообще сделать. Надо полностью перехватить перемещения мыши при выполнении драга, чтобы системный курсор не двигался. Но при этом умудриться выдавать событие QGraphicsSceneDragDropEvent в сцену. Скрыть курсор и нарисовать его в имедже драгаНазвание: Re: QDrag по сетке Отправлено: Гурман от Февраль 11, 2015, 11:11 Пока не видно, как это вообще сделать. Надо полностью перехватить перемещения мыши при выполнении драга, чтобы системный курсор не двигался. Но при этом умудриться выдавать событие QGraphicsSceneDragDropEvent в сцену. Скрыть курсор и нарисовать его в имедже драгаУ QCursor нет метода "скрыть". Есть методы, меняющие изображение, форму, позицию. Очевидно, они не влияют на обработку перемещения мыши. Название: Re: QDrag по сетке Отправлено: Igors от Февраль 11, 2015, 11:47 Скрыть курсор и нарисовать его в имедже драга Да, это ничего не даст - теперь дергаться будет "искусственный" курсор :) Придется отказаться от DnD если хотите чисто реализовать "прилипание". Чего впрочем следовало ожидать: в том же дызайнере когда новый виджет дропается на форму - курсор не скачет.[off]Когда-то давно читал книжку (уже и не помню название), там описывается такая модель поведения Цитировать - Почему бы Вам не... Т.е. любые доводы будут заведомо отвергнуты, потому что должно быть "только/именно так" - и точка. В программировании совместная работа с таким человеком невыносима :) - Да, но... Название: Re: QDrag по сетке Отправлено: Авварон от Февраль 16, 2015, 09:52 Сделайте специальный айтем, который будет показывать квадратик того, куда драгающийся айтем упадет. А курсор пусть двигается как хочет.
Название: Re: QDrag по сетке Отправлено: Гурман от Февраль 16, 2015, 10:28 Сделайте специальный айтем, который будет показывать квадратик того, куда драгающийся айтем упадет. А курсор пусть двигается как хочет. Курсор штатным QDrag таскает то же изображение, которое лежит на сцене, это обязательно. Объекты на сцене разные, у них разные изображения и размеры иконок. Если при этом еще какой-то квадратик будет ездить... :-\ Название: Re: QDrag по сетке Отправлено: Гурман от Февраль 16, 2015, 10:35 В программировании совместная работа с таким человеком невыносима :) Зато достигается именно поставленная цель, или хотя бы максимальное приближение к ней, а не "абы как бы чего-нибудь получилось". Впрочем, это уже полный оффтопик. Название: Re: QDrag по сетке Отправлено: Гурман от Февраль 16, 2015, 12:22 Если кому-то сильно интересно, чем закончилось: я остановился на том же режиме, как в дизайнере, то есть, перемещение свободное, привязка к сетке. Разумеется, пришлось нарисовать сетку из точек с помощью QGraphicsScene::drawBackground(). Я уверен, в дизайнере тоже так сделано потому что вариант со сменой способа перетаскивания при выходе со сцены получился бы слишком громоздким и плохо масштабируемым.
Собственно, констатация факта: есть вот такой недостаток Qt - невозможно сделать QDrag по сетке. Если кому-то интересно развитие, здесь соответствующий feature request (http://"https://bugreports.qt.io/browse/QTBUG-44396"). |