До сих пор я знаю три варианта:
widget->ensurePolished()
. qApp->style()->polish(widget)
. QCoreApplication::sendPostedEvents(widget, 0)
в виджетах до его показа. С Qt 5 вам не нужен второй аргумент, так как теперь он имеет значение по умолчанию 0. Другим решением вашей проблемы было бы просто не писать синхронный код вообще. Чтобы отобразить виджет верхнего уровня, когда он впервые показан:
while (widget->d_ptr->postedEvents)
QCoreApplication::sendPostedEvents(widget, 0);
Теперь вам гарантировано, что виджет виден и имеет правильный размер. Используйте геометрию виджета и переместите ее. Если вам нужна информация из всех виджетов, чтобы принять это решение, сохраните его в некоторой структуре данных и обработайте его только тогда, когда все виджеты есть. Если вы хотите предотвратить временную видимость виджетов в неправильных положениях, вы можете захотеть действовать вместо события изменения размера. Система компоновки и стилизации изменяет размер виджета верхнего уровня, подходящего для его содержимого. Вам необходимо удалить фильтр событий и обработать самую последнюю геометрию только тогда, когда больше нет событий для этого объекта после возврата из вызова sendPostedEvents
.
Следующее демонстрирует подход принудительной полировки и работает как в Qt 4.8.5, так и в 5.2.0. Я тестировал его как на 64-битной сборке на OS X, так и на 32-битной сборке на Windows.
Обратите внимание, что ни l1
, ни l2
не отображаются, но оба они сообщают правильный размер. l3
, но при запросе перед его показанием он сообщает о неправильном размере.
[/g0]
#include <QApplication>
#include <QLabel>
#include <QStyle>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QString style("QLabel { min-height:100px; max-height:100px; min-width: 300px; max-width:300px }");
a.setStyleSheet(style);
QLabel l1, l2, l3;
l1.ensurePolished(); // equivalent first/second methods
QCoreApplication::sendPostedEvents(&l2, 0); // third method
l3.setText(QString("l1: %1 x %2 l2: %3 x %4 l3: %5 x %6")
.arg(l1.width()).arg(l1.height())
.arg(l2.width()).arg(l2.height())
.arg(l3.width()).arg(l3.height()));
l3.setAlignment(Qt::AlignCenter);
l3.show();
return a.exec();
}
show()
. Это однопоточный код, и вы не будете делать что-то для себя, когда вы вызываетеsize()
! Таким образом, эту функцию можно вызывать только при вызовеshow()
, но , прежде чем она станет видимой еще i>.show()
делает кучу вещей, прежде чем виджет станет видимым. Документы действительно означают это: мы назовем это, когда вы назоветеshow()
, но прежде чем электроны попадут в люминофор на экране :) – Kuba Ober 24 January 2014 в 14:28setStyleSheet
имеет непосредственные последствия. Все, что гарантировано, заключается в том, что after i>, когда цикл события исчерпал очередь событий, эффекты установки стиля вступят в силу и будут видны. В Qt обновление отображения выполняется асинхронно из цикла событий. Поскольку вы не можете рисовать по требованию, не имеет никакого смысла, чтобы механизм стилизации делал вид, что вы можете. Визуальные и невизуальные эффекты стиля устанавливаются в одной и той же точке, асинхронно, поскольку соответствующие события сливаются из очереди. – Kuba Ober 29 January 2014 в 20:32