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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: (РЕШЕНО) Проблема с QSplitter и QGraphicsView::ensureVisible()  (Прочитано 4316 раз)
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

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


Просмотр профиля
« : Июнь 02, 2015, 22:25 »

Раньше использовалась сцена с ездящим по ней QGraphicsView, позиция которого отлично сохранялась и восстанавливалась в XML-файле. Вью лежал в лэйауте, лэйаут на QMainWindow. Позиции вью на сцене менялись при скроллинге сцены, размеры вью менялись вместе с соответствующим лэйаутом.

Сохранение делалось так:
Код:
    QDomElement view = xmldoc.createElement( "position" );
    QPointF viewportP = ui->graphicsView->mapToScene( QPoint(0,0 ) );
    view.setAttribute( "pointX", viewportP.x() );
    view.setAttribute( "pointY", viewportP.y() );
    QSizeF sizef = ui->graphicsView->viewport()->geometry().size();
    view.setAttribute( "sizeX", sizef.width() );
    view.setAttribute( "sizeY", sizef.height() );
    topNod.appendChild( view );
и т.д.

собственно, XML тут ни при чем, суть в записи 0,0-коррдинаты вьюпорта на схеме и его размеров. Восстановление так:
Код:
            ui->graphicsView->ensureVisible(
                               interface.attribute( "pointX" ).toDouble(),
                               interface.attribute( "pointY" ).toDouble(),
                               interface.attribute( "sizeX" ).toDouble(),
                               interface.attribute( "sizeY" ).toDouble(), 0, 0 );

И всё прекрасно работало. Но сделал этот же QGraphicsView частью QSplitter, которым он разделяется с другим QGraphicsView, чтобы можно было делить пространство между ними. QSplitter вертикальный (то есть, вью лежат рядом по горизонтали) в свою очередь подцеплен к тому лэйауту, в котором раньше просто лежал вью, и далее это все также лежит на QMainWindow. Проблемный вью находится в левой части сплиттера (в правой проблем не обнаружено, так как там положение вью не сохраняется за ненадобностью). Абсолютно всё рисовалось в Дизайнере. Кроме сцен, разумеется, они динамические, но без проблем работали последние 4 года. Запись и восстановление остались такими же, как и были, когда это всё нормально работало.

И с QSplitter поимел непонятное постоянное смещение вью по сцене. При восстановлении вью смещается по сцене всегда вниз и вправо. Самое странное - смещение зависит от позиции сплиттера, оно тем больше, чем левее сплиттер сдвинут. Когда сплиттер в его крайней правой позиции, то смещения вью вправо... нет вообще, он смещается только немного вниз.

Пока еще не выяснил, где происходит смещение - при вычислении mapToScene левого верхнего угла вью, или при его позиционировании в ensureVisible.

Может кто сказать, где я зевнул? Больше всего недоумения вызывает то, что сплиттер вызывает какое-то влияние на позиции вью на сцене. По идее этого вообще не должно быть.

ЗЫ: Установил, что сохраняется позиция правильно, то есть mapToScene(0,0) не виноват. Выяснил достоверно - сначала центровка вью по сцене (центровка работает достоверно, это проверенно), потом сохранение. В файле половина размера вью + координата угла == ровно половина размера сцены, как и должно быть. Значит, косячит ensureVisible(). Функция муторная, вызывает сдвиги скролл-баров, но еще и чего-то вычисляет.

ЗЫ2: Да...
Код:
            ui->graphicsView->ensureVisible(
                            interface.attribute( "pointX" ).toDouble(),
                            interface.attribute( "pointY" ).toDouble(),
                            interface.attribute( "sizeX" ).toDouble(),
                            interface.attribute( "sizeY" ).toDouble(), 0, 0 );
            qDebug() << interface.attribute( "pointX" ).toDouble()
                     << interface.attribute( "pointY" ).toDouble()
                     << ui->graphicsView->mapToScene( QPoint(0,0 ) );
Цитировать
32258 32442 QPointF(33008, 32472)
В замешательстве
« Последнее редактирование: Июнь 03, 2015, 19:19 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


Просмотр профиля
« Ответ #1 : Июнь 03, 2015, 09:32 »

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

Сообщений: 2921



Просмотр профиля
« Ответ #2 : Июнь 03, 2015, 11:29 »

Для начала в посте стоило бы переименовать QSlider в QSplitter, а QGraphicsWindow в QGraphicsView.
А позицию вьюпорта брать и потом восстанавливать через QGraphicsView::verticalScrollBar()/horizontalScrollBar()->value()/setValue().
Записан

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


Просмотр профиля
« Ответ #3 : Июнь 03, 2015, 13:22 »

Для начала в посте стоило бы переименовать QSlider в QSplitter, а QGraphicsWindow в QGraphicsView.
А позицию вьюпорта брать и потом восстанавливать через QGraphicsView::verticalScrollBar()/horizontalScrollBar()->value()/setValue().

Да, всё правильно, писал под вечер, когда уже устал бороться с этим недугом, перепробовал кучу вариантов

исправил свое первое сообщение

но насчет скроллбара... я с самого начала так и сделал, но что-то было тоже не так
« Последнее редактирование: Июнь 03, 2015, 13:36 от Гурман » Записан

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


Просмотр профиля
« Ответ #4 : Июнь 03, 2015, 13:34 »

приложите скриншоты как было и как стало...

а скриншоты зачем?... достаточно того, что координаты левого верхнего угла вьюпорта после установки ensureVisible не совпадают с теми, которые должны быть установлены

причем это зависит от позиции сплиттера:

33011 32512 QPointF(33746, 32542) - сплиттер в крайнем левом положении (при сдвиге левее он "схлопнет" вью слева от него), смещение по горизонтали = 735, по вертикали 30 (числа ничему вообще не соответствуют)
33381 32470 QPointF(33381, 32500) - сплиттер в крайнем правом положении, смещение по горизонтали отсутствует, по вертикали тоже 30

когда это было всё без сплиттера, то превосходно работало
« Последнее редактирование: Июнь 03, 2015, 13:42 от Гурман » Записан

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


Просмотр профиля
« Ответ #5 : Июнь 03, 2015, 14:02 »

позицию вьюпорта брать и потом восстанавливать через QGraphicsView::verticalScrollBar()/horizontalScrollBar()->value()/setValue().

сделал сейчас сохранение и восстановление значений скроллбара - все числа одинаковые, перед записью в файл, в файле, после чтения и после установки значений скроллбаров

но вью также сильно смещён относительно позиции при записи - по горизонтали теперь влево, по вертикали вверх, и также точно это зависит от положения сплиттера - в крайнем левом его положении смещение по горизонтали максимальное, в крайнем правом вообще отсутствует, по вертикали постоянное 30 пикселов

всё-таки что-то не то с этим QSplitter

ЗЫ: ensureVisible тоже через setValue у скроллбаров работает, то есть, что в лоб, что по лбу
« Последнее редактирование: Июнь 03, 2015, 14:05 от Гурман » Записан

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


Просмотр профиля
« Ответ #6 : Июнь 03, 2015, 18:13 »

Опытным путем установил размеры смещения по вертикали и горизонтали.

Ширина скроллбаров у меня установлена в системе, и равна 25. Минимальный размер проблемного QGraphicsView в Дизайнере задан равным 250х650. То есть, минимальный видимый размер 225х625. Смещение при размере вьюпорта по горизонтали 800 было равно 575, при размере 900 уже 675. По вертикали аналогично. То есть, смещение при вызове ensureVisible производится на величину, равную <текущий размер видимой части> - <минимальный размер QGraphicsView> - <толщина скроллбара>. Результат 100% воспроизводимый. В принципе, это можно компенсировать, если добраться до всех трёх величин.

При восстановлении установкой value()/setValue() скроллбаров смещения получаются такой же величины, как и с ensureVisible, но в другую сторону.

Кто-нибудь, где-нибудь, когда-нибудь встречал что-либо подобное в документации Qt, форумах, баг-репортах и т.д.?
« Последнее редактирование: Июнь 03, 2015, 18:30 от Гурман » Записан

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


Просмотр профиля
« Ответ #7 : Июнь 03, 2015, 19:19 »

Всё, нашел в чём проблема.

Чтобы не было видно процесс начальной загрузки сцены, я вызов show() для главного окна убрал после загрузки сцены (чтобы во время загрузки сплэш потом показать). Даже не сомневался, что все размеры виджетов на главном окне Qt пересчитает, независимо от того, видно это окно или нет. Вызов QMainWindow::show() производится в функции, срабатывающей по таймеру гарантированно после того, как QMainWindow и все его подвиджеты созданы. Это всё было сделано еще раньше, до использования QSplitter. И пока я его не прикрутил, всё было нормально, QGraphicsView сразу имел нужный размер и сцена показывалась после загрузки, как требуется. Но с QSplitter, если главное окно еще не показано на экране, почему-то для разделяемых им виджетов используются их минимальные размеры. То есть, получается, что сцена рисуется в тени на QGraphicsView минимального размера, а когда вызывается QMainWindow::show(), то окно раскрывается полностью, и сцена оказывается смещена.

Перенес вызов QMainWindow::show() до загрузки сцены - и смещение пропало. Проблема решена. Но с QSplitter явно что-то не так.
« Последнее редактирование: Июнь 03, 2015, 19:28 от Гурман » Записан

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


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