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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Стартовое окно в процессе запуска основного приложения  (Прочитано 7266 раз)
TaIRou
Гость
« : Октябрь 24, 2012, 20:26 »

доброго времени суток!

В процессе запуска приложения происходит создание многих объектов в том числе и визуальных.
Поэтому от момента старта приложения до момента его визуализации на экране проходит ощутимое количество времени.
Чтобы пользователь был осведомлен, что запуск приложения ведется, необходимо вывести какое-либо окно, свидетельствующее о процессе запуска.

В качестве такого окна был задействован QProgressDialog, но так как он создан в том же потоке, в котором создаются другие "тяжелые" виджеты, то он "заморожен" и иногда некоректно отображается в виде пустого прямоугольника.

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

спасибо.
Записан
mutineer
Гость
« Ответ #1 : Октябрь 24, 2012, 20:42 »

вызывай периодически QApplication::processEvents()
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #2 : Октябрь 25, 2012, 06:46 »

Вообще, для этих целей целый класс есть  - QSplashScreen.
Читать тут http://qt-project.org/doc/qt-4.8/QSplashScreen.html
И, таки-да, регулярный вызов processEvents.

Код
C++ (Qt)
QPixmap pixmap(":/splash.png");
QSplashScreen *splash = new QSplashScreen(pixmap);
splash->show();
 
... // Loading some items
splash->showMessage("Loaded modules");
 
qApp->processEvents();
 
... // Establishing connections
splash->showMessage("Established connections");
 
qApp->processEvents();
 
Записан
TaIRou
Гость
« Ответ #3 : Октябрь 25, 2012, 17:03 »

Замечательно, спасибо ребят за наводку!
Записан
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #4 : Октябрь 25, 2012, 19:51 »

я думаю, вместо processEvents() достаточно splash->repaint().
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Октябрь 25, 2012, 21:20 »

я думаю, вместо processEvents() достаточно splash->repaint().
Это вроде бы кажется бесспорным, но проверка не подтверждает. Запускаем прилагаемый примерчик из консоли, после того как repaint вернуло управление - окно не перерисовано (OSX 10.6.8 )
Код
C++ (Qt)
#include <QtGUI>
 
int thePaintNo = 0;
 
class MyDialog : public QDialog {
public:
virtual void paintEvent( QPaintEvent * )
{
printf("paintEvent %d\n", thePaintNo);
QPainter painter(this);
QRect R(0, 0, 100, 100);
switch (thePaintNo % 3) {
case 0:
painter.fillRect(R, QBrush(Qt::red));
break;
case 1:
painter.fillRect(R, QBrush(Qt::green));
break;
case 2:
painter.fillRect(R, QBrush(Qt::blue));
break;
}
++thePaintNo;
}
};
 
int main( int argc, char** argv )
{
QApplication app(argc, argv);
MyDialog dlg;
dlg.show();
 
printf("before repaint\n");
dlg.repaint();
printf("after repaint\n");
getchar();
 
return app.exec();
}
 
Записан
mutineer
Гость
« Ответ #6 : Октябрь 25, 2012, 21:25 »

я думаю, вместо processEvents() достаточно splash->repaint().
Это вроде бы кажется бесспорным, но проверка не подтверждает. Запускаем прилагаемый примерчик из консоли, после того как repaint вернуло управление - окно не перерисовано (OSX 10.6.8 )

Repaint у сплешскрина отличается от обычного
Цитировать
void QSplashScreen::repaint ()

This overrides QWidget::repaint(). It differs from the standard repaint function in that it also calls QApplication::flush() to ensure the updates are displayed, even when there is no event loop present.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Октябрь 25, 2012, 23:30 »

Repaint у сплешскрина отличается от обычного
Пробовал и вставлять app.flush() и наследоваться от QSplashScreen, и оба вместе Улыбающийся Не катит, квадрат красный. Вызываю processEvents - все норм, зеленый
Записан
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #8 : Октябрь 25, 2012, 23:31 »

я думаю, вместо processEvents() достаточно splash->repaint().
Это вроде бы кажется бесспорным, но проверка не подтверждает. Запускаем прилагаемый примерчик из консоли, после того как repaint вернуло управление - окно не перерисовано (OSX 10.6.8 )

Предполагаю потому, что окно всё ещё скрыто в момент repaint(). repaint() нужно звать после каждой установки значения в QProgressDialog, когда он точно видим. У меня что-то подобное есть, только не во время старта, а во время работы программы.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Октябрь 26, 2012, 13:44 »

Предполагаю потому, что окно всё ещё скрыто в момент repaint(). repaint() нужно звать после каждой установки значения в QProgressDialog, когда он точно видим.
Зачем "полагать" если можно просто компильнуть и увидеть то окно с красным квадратом?  Улыбающийся
Записан
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #10 : Октябрь 26, 2012, 14:35 »

Зачем "полагать" если можно просто компильнуть и увидеть то окно с красным квадратом?  Улыбающийся

Посмотрел на винде - рисуется красный квадрат, даже если использовать update() и processEvents(). Я спутал с Linux версией, где окно показыватся асинхронно. В макоси окно показывается тоже синхронно, как и в винде? Если да, то понятно, почему рисуется красный квадрат. Обновление окна происходит принудительно и один раз, и paintEvent() вызывается только один раз. Поэтому мы видим красный квадрат.
« Последнее редактирование: Октябрь 26, 2012, 14:37 от Alex Custov » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Октябрь 26, 2012, 14:55 »

Посмотрел на винде - рисуется красный квадрат, даже если использовать update() и processEvents(). Я спутал с Linux версией, где окно показыватся асинхронно. В макоси окно показывается тоже синхронно, как и в винде? Если да, то понятно, почему рисуется красный квадрат. Обновление окна происходит принудительно и один раз, и paintEvent() вызывается только один раз. Поэтому мы видим красный квадрат.
У меня так
1) Убираю repaint или вставляю getchar() перед repaint. Окно показано, квадрат красный. То есть show окно полностью нарисовало

2) Вставляю app.processEvents после repaint. Все норм, зеленый квадрат, paintEvent вызвано дважды

По поводу "синхронно" на OSX - ну не знаю что тут считать синхронным. Но буферирование налицо. Пример: если мое окно закрыто другими, я могу спокойно их отодвинуть, мое окно отрисуется со всем содержимым без всяких вызовов paint (буфер)
Записан
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #12 : Октябрь 26, 2012, 15:09 »

2) Вставляю app.processEvents после repaint. Все норм, зеленый квадрат, paintEvent вызвано дважды

на винде одиножды, квадрат остаётся красным. Собственно в чём проблема, если paintEvent() точно вызывается? А если он вызывается, то QProgressDialog будет нормально отрисован, что с processEvents(), что без.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Октябрь 26, 2012, 15:17 »

Собственно в чём проблема, если paintEvent() точно вызывается?
Так один раз (в show). Напр если заменить getchar на длинные расчеты - квадрат остается красным и вызов repaint не помогает
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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