Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Гурман от Февраль 22, 2015, 22:00



Название: (РЕШЕНО) Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: Гурман от Февраль 22, 2015, 22:00
Есть бесконечная сцена, которая видна в стандартном прямоугольном QGraphicsView. Пользователь видит скроллы и может менять положение вьюпорта на сцене.

Изменение положения скроллов у меня ловится, и по нему взводится флаг необходимости сохранения сцены, поскольку изменилось положение вьюпорта, которое сохраняется в файле сцены. Тут всё было бы хорошо, если бы не одна неожиданность - Qt зачем то двигает 1 скролл (не выяснил какой - не интересно), уже после того, как отработал мой конструктор главного окна, появилось само окно, загрузилась и нарисовалась сцена, и я сбросил все флаги изменений. В результате получается, что сцена после запуска всегда оказывается изменена, и надо её сохранять. Хотя после начального запуска и загрузки сцена должна считаться неизмененной. Я это обошел с помощью простого хака - флаг, который установлен в конце конструктора, проверяется в приемнике сигнала сдвига скролла, и один сигнал скролла игнорируется, после чего флаг сбрасывается. Так всё работает как необходимо.

Но. Это у меня сейчас Qt 4.7, и похоже, что это баг. На это намекает сигнал об изменении только 1-го скролла, хотя у моей сцены их 2, а также отсутствие какой-либо разумной необходимости его менять, поскольку я сам нигде после загрузки сцену не меняю до тех пор, пока это не сделает уже пользователь.

И как это работает в Qt 5.x? Может там баг уже исправлен?

Кто может проверить? Если кто делает что-нибудь похожее?? Сцену бесконечного размера с просмотром через окно в редакторе - в конструкторе класса главного окна надо накидать на неё чего-нибудь, у обоих скроллов соответствующего QGraphicsView сигналы valueChanged(int) должны быть привязаны к слоту класса главного окна, в котором выводится qDebug << счетчик; и этот счетчик сброшен в 0 в самом конце конструктора класса главного окна. Что покажет счетчик после запуска и отработки конструктора?


Название: Re: Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: Bepec от Февраль 22, 2015, 22:17
Ну как бы логично всё. Ты всё создал, появляется окно, нарисовалась сцена, испускается 2 сигнала изменения скроллов - горизонтального и вертикального :)

Но на деле тебе проще выводить в дебаг отправителя сигнала и мониторить состояние полосочек) Сразу увидишь вредителя.

PS если выложишь проект, я могу позырить.

PPS нет, сам я не могу выложить сцену, привязаться к сигналам и мониторить - мне лень и мне нужен проект :D


Название: Re: Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: Гурман от Февраль 22, 2015, 23:58
Лишний сигнал приходит ОДИН, хотя скроллов ДВА. И сигналы при изменении сцены приходят РАНЬШЕ, когда я сцену загружаю и отрисовываю. В эти моменты приходят два сигнала, как положено. И когда MainWindow::show() вызываю, тоже приходят положенные два сигнала. Но потом, когда я уже всё закончил делать, почему-то приходит ЕЩЕ ОДИН.  ??? Ну я бы согласился еще как-то, что могут два сигнала прийти, мало ли какая-то отрисовка внутри Qt потом произошла. Хотя зачем, если уже всё отрисовано, и я ничего со сценой не делаю? Но приходит только один сигнал. Я в полном недоумении.

Отправителя этого сигнала не вижу особого смысла в дебаге выводить - я в дебаге поймал этот сигнал, вижу стек, это сплошь Qt-шные потроха. В стеке вызовов самый нижний назывался что-то вроде qt_internals... Ну посмотрю я, кто отправитель - и что с ним делать?

Проект не пришлю, приватная разработка, несколько ноу-хау.

Этот глюк я обошел, но мне не ясно, что будет в версиях Qt 5.x.


Название: Re: Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: Bepec от Февраль 23, 2015, 00:24
Подытожим - в проблеме не разобрались, считаем это багом, проверять не хотим :)

PS тему можно удалять, никакой информации она не несёт.


Название: Re: Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: Гурман от Февраль 23, 2015, 00:34
Тема содержит вопрос/просьбу к тем делает что-то похожее на более новых версиях Qt - проверить как они ведут себя в похожей ситуации. Поэтому ничего удалять не надо.


Название: Re: Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: Old от Февраль 23, 2015, 08:05
Тема содержит вопрос/просьбу к тем делает что-то похожее на более новых версиях Qt - проверить как они ведут себя в похожей ситуации. Поэтому ничего удалять не надо.
Да уже поставили бы себе пятерку и проверили на ней. :)
У меня сейчас как правило, установлены Qt 5.X, 4.8.6, 4.7.X. В разных проектов используются разные версии. Все спокойно уживается и используется.


Название: Re: Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: Igors от Февраль 23, 2015, 12:41
Но потом, когда я уже всё закончил делать, почему-то приходит ЕЩЕ ОДИН.  
Что значит "почему-то"?. Точка прихода есть, стек вызовов есть, значит в отладчике должно быть видно "почему"


Название: Re: Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: xokc от Февраль 23, 2015, 14:03
Кто может проверить? Если кто делает что-нибудь похожее?? Сцену бесконечного размера с просмотром через окно в редакторе - в конструкторе класса главного окна надо накидать на неё чего-нибудь, у обоих скроллов соответствующего QGraphicsView сигналы valueChanged(int) должны быть привязаны к слоту класса главного окна, в котором выводится qDebug << счетчик; и этот счетчик сброшен в 0 в самом конце конструктора класса главного окна. Что покажет счетчик после запуска и отработки конструктора?
Проект не пришлю, приватная разработка, несколько ноу-хау.
Какая интересная позиция: сделайте, кто-нибудь за меня тестовый проект и проверьте на своем комплекте. А то у меня проблема, но нет на это времени, мне лень... (нужное подчеркнуть). Даже интересно найдутся добровольцы? А то у меня тоже есть ряд проблем, которые стоило-бы проверить, но мне лень.


Название: Re: Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: Igors от Февраль 23, 2015, 14:46
Какая интересная позиция: сделайте, кто-нибудь за меня тестовый проект ...
Он очень занят, ему надо "поднимать проект", там тонна работы. А другим не надо, они все равно фигней маются, вот пусть обслуживают "пахаря". 


Название: Re: Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: Bepec от Февраль 23, 2015, 14:49
Тссс ) а темку счас реально надо удалять :D


Название: Re: Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: Гурман от Февраль 23, 2015, 14:51
Что значит "почему-то"?. Точка прихода есть, стек вызовов есть, значит в отладчике должно быть видно "почему"

В стеке видны только Qt-шные вызовы. 78 штук. Ни одного моего. Можно конечно, полезть по ним, но пока до этого руки не дошли.

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

Тссс ) а темку счас реально надо удалять :D

не надо - просто кто не может ничем помочь, пусть не реагирует


Название: Re: Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: Гурман от Февраль 23, 2015, 15:25
Ну посмотрел я стек вызовов. Уже после того, как отработала инициализация ui, после того, как созданы сцены, на сцены помещены айтемы, все нужные объекты уже существуют, выведены на экран и работают - начинается тряска. Приложение запостило event, вызывающий дальше обновление всего интерфейса. И при этом обновлении есть в середине вызов centerView(lastCenterPoint), в котором якобы горизонтальный скроллбар смещается. Хотя никто и ничто его на самом деле не смещает и визуально никакого смещения не видно. Вертикальный при этом никуда не смещается, и от него сигнала нет. Ошибка возникает при округлении qreal до int, поскольку косяк в этой строке (функция void QGraphicsView::centerOn(const QPointF &pos)):

Цитировать
horizontalScrollBar()->setValue(int(viewPoint.x() - width / 2.0));
- все наклонные типа qreal

а в числах там 32378.0-845/2.0 = 31955.5 - вот эти 0.5 и дают ошибку

и что забавно, для вертикального скролла такое вычисление не вызывается (хотя в коде есть), и у него ошибка не возникает

ЗЫ, посмотрел исходники Qt 5.4 в сети - там та же фигня.

Вот теперь ветку можно закрыть. Но удалять не надо.


Название: Re: Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: Гурман от Февраль 25, 2015, 21:00
Поторопился я объявить этот глюк решенным. Нифига. Даже при всех нормальных значениях Qt умудряется сдвигать вьюпорт на 1 пиксел после всех инициализаций и загрузок. То есть, мой хак работает, но не всегда.

Я попытался сбросить признак изменения сцены после того, как приложение входит в eventLoop, стандартным приемом с однократным таймером. ТОЖЕ НИФИГА. Таймер срабатывает, признак сбрасывается, но вьюпорт сдвигается уже ПОСЛЕ этого.  >:(

Код:
...... это конец конструктора MainWindow
    onstart.singleShot( 0, this, SLOT(started()) );
}

void MainWindow::started()
{
    qDebug() << "reset";
    schemeChanged( false );
}

// сюда попадает при сдвиге скроллов
void MainWindow::sceneViewportChange(int)
{
    schemeChanged( true );
    qDebug() << "set";
}

и вывод в консоль:

Цитировать
reset
set
set

ППЦ. Как это побороть - не знаю пока. Нет идеи...   :-\


Название: Re: Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: Гурман от Февраль 25, 2015, 21:28
ВАХ!

Код:
    onstart.singleShot( 1, this, SLOT(started()) );

Цитировать
set
set
reset

Разве где-то описано, что при 0 времени для singleShot таймер сработает ДО входа в eventLoop, а при не 0 - ПОСЛЕ??

Хотя может быть просто за 1 мс оно успело сморозить и смещение, и обработать сигнал о нём.


Название: Re: Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: Bepec от Февраль 25, 2015, 22:43
написано что если значение равно 0, то идёт вызов функции :) Причем в документации по таймеру даже.


Название: Re: Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: Гурман от Февраль 25, 2015, 22:56
В описании QTimer про 0 вот что написано:

Цитировать
As a special case, a QTimer with a timeout of 0 will time out as soon as all the events in the window system's event queue have been processed.

То есть, сработает так скоро, как были обработаны все события в очереди оконной системы.

А в описании singleShot( time, object, slot ) про время вообще ни слова, очевидно тоже самое, что у таймера с заданным временем.


Название: Re: Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: Bepec от Февраль 25, 2015, 23:04
Ну я лично в исходниках видел 
Код:
if == 0
 вызов функции
:)
Хотя как обычно добавлю - новые версии могли измениться, но врядли :)


Название: Re: Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: Гурман от Февраль 25, 2015, 23:06
Ну я лично в исходниках видел 
Код:
if == 0
 вызов функции
:)
Хотя как обычно добавлю - новые версии могли измениться, но врядли :)

Хе, так эта проверка и вызов могут (точнее, судя по описанию должны) быть ПОСЛЕ того, как отработают события оконной системы. И таймаут запускается ПОСЛЕ этого. Разумеется, перед запуском всегда будет проверка времени на 0, ибо если 0, то какой смысл таймер дергать, можно сразу вызывать. Но к обработке событий это не имеет никакого отношения.


Название: Re: Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: Bepec от Февраль 26, 2015, 01:08
Эммм в статическом методе SingleShot, я имею в виду. Сразу при вызове) Мгновенно) бесповоротно :D


Название: Re: Лишнее изменение скролла после работы конструктора в других версиях Qt
Отправлено: Гурман от Февраль 26, 2015, 01:59
Значит недокументированное поведение, которое противоречит интуитивно ожидаемому по смежным описанным в документации функциям. Нехорошо это...