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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: (РЕШЕНО) QDrag по сетке  (Прочитано 12077 раз)
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

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


Просмотр профиля
« : Февраль 09, 2015, 12:53 »

3 года назад достаточно было перетаскивать айтемы между двумя сценами и виджетом. Это было сразу сделано с использованием QDrag, и нормально работало. Сейчас понадобилось в одной из сцен (назовем ее холст) иметь сетку (grid) - если драг переносится на холсте, или перетаскивается на холст из другой сцены (назовем её палитра), то над холстом он должен двигаться по узлам сетки. При выходе из холста айтем должен двигаться свободно, и роняться в палитру или третий виджет (назовем его мусорник). После изучения документации не видно никакой возможности управлять координатами события QGraphicsSceneDragDropEvent, которое принимает холст. Получить можно, проверить на попадание в узел сетки можно, но принудительно перемещать - не видно как.

Переделывать QDrag в перетаскивание простых QGraphicsItem по холсту (так рекомендуют делать простую сетку) очень не хочется. Возможность перетаскивания с холста в мусорник, с холста в палитру и с палитры на холст должна не измениться. То есть, придется еще мостырить преобразование перемещения айтемов в QDrag при выходе из с холста, и обратное преобразование QDrag в перемещение айтемов при входе в холст. Бутерброд получится слишком неуклюжий.

Может я что-то упускаю? Кто-нибудь делал похожее? Может ли как-нибудь помочь класс QGraphicsGridLayout? Насколько я понимаю, он предназначен для автоматической компоновки элементов управления на диалогах, которые создаются динамически. Не вижу, можно ли его применить для реализации сетки, если да, то как.
« Последнее редактирование: Февраль 23, 2015, 22:49 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Bepec
Гость
« Ответ #1 : Февраль 09, 2015, 13:17 »

Получаете координаты драга, при попадании на сетку перемещаете курсор к ближайщей точке привязки. Драг соответственно пойдёт туда же.

Разве нет?
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

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


Просмотр профиля
« Ответ #2 : Февраль 09, 2015, 13:36 »

Не, проблема есть. QCursor::setPos() перемещает в координатах экрана. Чтобы получить координаты экрана, надо преобразовать в них координаты QWidget. Но QGraphicsScene не наследует из QWidget. А я получаю в событии QGraphicsSceneDragDropEvent значения в системе координат QGraphicsScene. Не могу пересчитать их в реальные координаты экрана. Теоретически, можно бы посчитать сетку только для курсора, когда он находится над холстом. Но это будет косяк из косяков - сетка будет перемещаться по холсту при изменении его положения внутри окна. Холст то огромного размера...

Кстати, даже если бы можно было пересчитать координаты, всё равно косяк бы получился. Рядом с рамками холста курсор бы скакал, вместо того, чтобы просто отрываться.
« Последнее редактирование: Февраль 09, 2015, 13:41 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Bepec
Гость
« Ответ #3 : Февраль 09, 2015, 13:47 »

Плавность перемещения это другая проблема. Что вполне решается начальной привязкой к одной ячейке и плавным переходом к другим узлам.

А координаты пересчитываться должны как то, хотя я не задавался этим вопросом.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

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


Просмотр профиля
« Ответ #4 : Февраль 09, 2015, 14:15 »

Разные системы координат - есть виджет, в котором окно. У него своя система координат. Сцена перемещается внутри этого окна, у неё своя система координат, и она перемещается относительно виджета. Мне нужно привязываться к координатам на сцене, а не к виджету. Пересчета координат сцены в координаты виджета, в котором отображается сцена, я не вижу.

Плавность не волнует пока. Скачки были бы при перемещении курсора от точек привязки, наиболее близких к границам окна. От них курсор выпрыгывал бы сразу за границу, математически на следующую точку привязки, но она уже не видна, находится под рамкой. И дальность выпрыгивания зависела бы от того, как близко точка привязки находится к границе окна. Весьма неадекватное было бы поведение.
« Последнее редактирование: Февраль 09, 2015, 14:18 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Bepec
Гость
« Ответ #5 : Февраль 09, 2015, 14:31 »

Насчёт пересчёта координат - подумайте, поищите варианты. Я близко не работал со сценой, тут не подскажу.
Насчёт "выпрыгиваний" - это бред. Всё решается просто, буквально надо написать поведения для 5-7 случаев. И будет у вас плавное не скачущее поведение.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Февраль 09, 2015, 14:40 »

Не уверен что прыгающий/прилипающий курсор - то что нужно. Может лучше сделать drag полурозрачным, а самому подсвечивать точку привязки
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

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


Просмотр профиля
« Ответ #7 : Февраль 09, 2015, 15:10 »

Не уверен что прыгающий/прилипающий курсор - то что нужно. Может лучше сделать drag полурозрачным, а самому подсвечивать точку привязки

Нет, когда драг попадает в холст, нужен именно прилипающий драг. Также, как во многих граф. редакторах. Теоретически, можно было бы сделать приклеивание к сетке при дропе - но меня лично такой вариант всегда раздражал. Когда тащишь объект по сетке шагами, то ясно, где он останется. А когда бросаешь, а он прилипает немного в сторону, это злит.
« Последнее редактирование: Февраль 09, 2015, 15:29 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

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


Просмотр профиля
« Ответ #8 : Февраль 09, 2015, 23:05 »

Можно пересчитать координаты сообытия на сцене в координаты курсора.

QCursor::setPos( views().at(0)->mapToGlobal( views().at(0)->mapFromScene( event->scenePos() ) ) );

Иногда Qt мне не нравится...
Записан

2^7-1 == 127, задумайтесь...
Bepec
Гость
« Ответ #9 : Февраль 10, 2015, 02:15 »

Никто не идеален, ничто не идеально...
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #10 : Февраль 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.
Записан

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


Просмотр профиля
« Ответ #11 : Февраль 10, 2015, 13:59 »

Средствами QDrag такое не реализуешь.

На самом деле, почти реализовал. Верес прав насчет перемещения драга за системным курсором. Если изменять QCursor::setPos() то курсор перемещается, и драг вместе с ним. Предложенный Вересом вариант почти работает, драг прилипает к координатам сетки, я их просто арифметически вычисляю при перемещении в методе QGraphicsScene::dragMoveEvent(...) и перевожу в координаты системного курсора. Единственное что пока не поборол - курсор продолжает перемещаться за системной мышью, в результате драг "сопротивляется". Когда мышь двигаешь - он сначала подрагивает в нужном направлении (отрывается, чуть перемещается, потом приклеивается обратно). Потом перепрыгивает на ближайшую точку сетки в нужном направлении. Это не юзабельно, надо что-то придумать, как-то отключить системное перемещение курсора за мышью. Разумеется, при этом не потеряв переносимость.
Записан

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

Сообщений: 2921



Просмотр профиля
« Ответ #12 : Февраль 10, 2015, 14:16 »

Это не юзабельно, надо что-то придумать, как-то отключить системное перемещение курсора за мышью. Разумеется, при этом не потеряв переносимость.
Я же вроде объяснил, что это не реализуемо.
Записан

Qt 5.11/4.8.7 (X11/Win)
Bepec
Гость
« Ответ #13 : Февраль 10, 2015, 14:45 »

Не особо понял проблему, если распишите поподробнее (пойдёт и гифка допустим), можно будет подумать.

to GreatSnake: мне сотни раз говорили эту фразу. Единственный вывод, который я из неё вынес - нет не реализуемого, есть труднореализуемое.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

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


Просмотр профиля
« Ответ #14 : Февраль 10, 2015, 15:07 »

Не особо понял проблему, если распишите поподробнее (пойдёт и гифка допустим), можно будет подумать.

Да лучше уже не описать. Могу только повторить. Курсор реагирует на физические перемещения мыши, он двигается в соответствии с ними. Как обычно двигается. Но я его еще и принуждаю устанавливаться в точки сетки - он устанавливается. Результат выглядит так - если медленно везти мышь, драг просто дергается на месте возле своего узла. Если интенсивнее, то он подергивается, но при этом перепрыгивает по узлам. Но не подряд по узлам сетки, а рывками, перескакивая несколько узлов. Это потому, что на драг влияют не только мои команды установки setPos(), но и системные перемещения мыши. Я ведь получаю в QGraphicsSceneDragDropEvent координаты после того, как курсор прилип к узлу сетки. А чтобы перемещать мышь отдельно, а курсор отдельно, надо получать в событии координаты мыши, как если бы сетки не было. То есть, нужно еще перехватывать тики мыши, делать "виртуальный курсор", который ничего не знает про сетку, и его координаты использовать в качестве исходных. То есть, разделить экранный курсор и перемещение мыши.
Записан

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


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