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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: (РЕШЕНО) Какая-то хрень при saveGeometry() у QWidget на QDialog  (Прочитано 10852 раз)
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

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


Просмотр профиля
« : Апрель 22, 2015, 12:18 »

У меня в приложении для хранения состояния окон используется пара saveGeometry() и restoreGeometry(). Для окон диалогов, наследующих от QDialog и QMainWindow всё превосходно давно работает. Никаких проблем не было.

Надо сделать сохранение положения виджетов контролов, размещаемых пользователем на QDialog. Они все тоже QWidget, и в этом отношении от окон не отличаются. Значит использую хорошо отлаженную функцию сохранения и восстановления, просто один-в-один. Но получаю какой-то бред. После исключения всего кода, где могли бы быть ошибки (хотя их нет, работает уже несколько лет без нареканий) осталось вот это:

Код:
    qDebug() << pos();
    restoreGeometry( saveGeometry() );
    qDebug() << pos();

На выходе
Цитировать
QPoint(0,0)
QPoint(0,68)
Что за?Непонимающий.... Непонимающий
Дальше замечаю еще более странное поведение - если перед вызовом saveGeometry() вертикальная координата виджета на диалоге была меньше 68, то saveGeometry() упорно возвращает 68. Если больше 68 - то возвращается правильная вертикальная координата, как есть. Горизонтальную координату saveGeometry() всегда возвращает правильную.

Проверил с несколькими виджетами - QPushButton (наследует QAbstractButton), QSlider (QAbstractSlider), QComboBox (наследует QWidget напрямую) - везде результат совершенно одинаковый.

Может я пропустил чего? В Интернете репортов про такой баг не видно. Может надо какие-то нетривиальные настройки делать? Перерыл еще раз описания - ничего подходящего.
« Последнее редактирование: Апрель 22, 2015, 22:50 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Bepec
Гость
« Ответ #1 : Апрель 22, 2015, 12:46 »

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

PS скорее всего вы не учитываете какой то виджет, который не сохраняется и/или настройки лайаутов и иже с ними.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

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


Просмотр профиля
« Ответ #2 : Апрель 22, 2015, 12:59 »

Не... вот этот код, который выше - это код в самом виджете, в его конструкторе. Никаких других виджетов нет, он на диалоге один единственный.

То, что код в конструкторе виджета, и выполняется до привязки виджета к виджету-родителю - значения не имеет. Код выполняется идентично как до, так и после этой привязки. Проверялись все случаи.

« Последнее редактирование: Апрель 22, 2015, 13:02 от Гурман » Записан

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


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

Вот же шайтан... Во-первых, несмотря на то, что pos() виджета до привязки к родительскому виджету возвращает 0,0 - saveGeometry() почему-то считает совершенно иначе, и возвращает совершенно другую координату. Можно сказать, что случайную. То есть, у pos() одни координаты, а у saveGeometry() совершенно другие. Но дальше хуже - после привязки к родителю, виджет начинает считать координату, ранее записанную в геометрии, как нулевую на родителе. И если виджет перемещается по родителю, то move(x,y) визуально нормально перемещает (за это отвечает родитель), но в самой геометрии координаты выше-левее той, что была прописана при привязке - похоже не изменяются. Вместо них остается координата, которая была во время привязки.

То есть, после привязки виджета к родительскому виджету, чтобы избежать таких глюков, надо обязательно делать move(0,0), а только потом восстанавливать его координаты с помощью restoreGeometry().

И опять же - это нигде не описано, и хрен догадаешься.

PS Не, нифига! Даже перемещение после привязки не помогает - координата на родителе, которая прошита в geometry при привязке, не изменяется.
« Последнее редактирование: Апрель 22, 2015, 14:16 от Гурман » Записан

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 : Апрель 22, 2015, 15:47 »

saveGeometry() похоже правильно работает, но restoreGeometry() похоже что нет
Записан

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

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Апрель 22, 2015, 15:53 »

Пока все не нарисовано на экране - размеры и позиция могут быть !филькина грамота", недавно было подобное
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

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


Просмотр профиля
« Ответ #6 : Апрель 22, 2015, 17:31 »

В данном случае от нарисованности не зависит. Тут я пристегиваю тестовый проект, в котором баг вылазит во всей своей красе. Просьба тем, кто работает на Qt новее 4.7 - проверить, что выдаст в консоль. У меня с Qt 4.7 выдаёт

Цитировать
Запускается ..........\Integrator.exe...
QPoint(0,0)
QPoint(0,68)
..........\Integrator.exe завершился с кодом 0

Особенно интересует версия 4.8 - она от 4.7 не сильно отличается, если в ней бага нет, то можно переползти на неё.
Записан

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

Сообщений: 11445


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

Qt 5.4 OSX, вывод
Цитировать
QPoint(0,0)
QPoint(0,22)
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

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


Просмотр профиля
« Ответ #8 : Апрель 22, 2015, 19:05 »

ППЦ...  Грустный

Причем если до вызова restoreGeometry(), вызовом move(x,y) переместить кнопку ниже 68 у меня, или ниже 22 в OSX - то вертикальная координата восстановится нормально. Впрочем 68 и 22 - это случайные числа.

Что характерно - с полными окнами, типа QDialog или QMainWindow это не проявляется, они восстанавливаются нормально, специально проверял, загоняя их в разные места десктопа.

Кто-нибудь еще на Qt 5.x в Виндах, Линухе? Для основательности багрепорта...
« Последнее редактирование: Апрель 22, 2015, 19:19 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Bepec
Гость
« Ответ #9 : Апрель 22, 2015, 20:07 »

А ты добавь restoreGeometry в слот, который вызови таймером через секунду )

Что получится? Веселый
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

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


Просмотр профиля
« Ответ #10 : Апрель 22, 2015, 20:15 »

Через секунду после чего? Завершения инициализации приложения? Да тоже самое получится - у меня в реальном приложении всё это далеко после всяких инициализаций происходит с таким же результатом.
« Последнее редактирование: Апрель 22, 2015, 20:21 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Bepec
Гость
« Ответ #11 : Апрель 22, 2015, 20:34 »

После загрузки всех ваших конструкций и прорисовки Улыбающийся
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

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


Просмотр профиля
« Ответ #12 : Апрель 22, 2015, 20:36 »

ДА ПОХЕРН ГДЕ!

ААА!!! Я нашел дырку! Это в Qt даже не локальная дырка - это системная дырка. Igors, ваши 22 - это высота тулбара на вашем рабочем столе, причем он у вас наверху экрана находится. Так? Подмигивающий

Они в restoreGeometry() вообще не считают, что у виджета может быть родителем другой виджет. Работает так, как будто виджет всегда лежит строго на десктопе. ЗАБЫЛИ ПРО ИЕРАРХИЮ ВИДЖЕТОВ...

Как я это нашел? Выдернул исходник restoreGeometry(), удалил там некоторый явно не нужный в моем случае код, пришил к тестовому проекту, и пошел отладчиком. И набрел на вызов, где появляется число 68:

Код:
    restoredFrameGeometry.moveTop(qMax(restoredFrameGeometry.top(), availableGeometry.top()));

- и это не в условном выполнении, а на основном уровне функции, то есть ВСЕГДА

Так вот availableGeometry.top() - это допустимая геометрия всего десктопа. В моем случае там x1 = 0, x2 = 1919, y1 = 68, y2 = 1199. Потому что 68 - это у меня ширина двойного таскбара наверху рабочего стола, МАТЬ ЕГО!!!....  Злой
« Последнее редактирование: Апрель 22, 2015, 20:41 от Гурман » Записан

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


Просмотр профиля
« Ответ #13 : Апрель 22, 2015, 20:48 »

Но самое приятное - это то, что баг легко обходится. Эта функция restoreGeometry() вообще мне не нужна. В ней более 70 строк замудренного (с использованием QDataStream) кода - сплошные проверки допустимости восстановления. И всё сводится к двум вызовам:

Код:
        move(restoredFrameGeometry.topLeft() + offset);
        resize(restoredNormalGeometry.size());

Которые я и сам сделаю для восстановления 4-х целых чисел, описывающих геометрию встроенных виджетов.

Даже не знаю - писать баг-репорт, или нет... Наверно надо, хотя есть сомнения, что будут исправлять. Наверняка начнут отнекиваться, типа того что restoreGeometry для встроенных виджетов не предназначено (в доках про это ни слова!). Хотя зря, вполне может работать.
« Последнее редактирование: Апрель 22, 2015, 20:51 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Bepec
Гость
« Ответ #14 : Апрель 22, 2015, 21:27 »

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

PS скорее всего вы не учитываете какой то виджет, который не сохраняется и/или настройки лайаутов и иже с ними.

На мой взгляд не баг, а фича Улыбающийся Ну или ваш недосмотр Веселый
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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