QMessageBox is not positioned correctly when shown during startup
-
Hi
I had same issue so i usedvoid MainWindow::showEvent ( QShowEvent* ev ) { QMainWindow::showEvent ( ev ); emit MainWindowLoaded(); }The other classes then use the MainWindowLoaded signal to know mainwin should be up now.
Q_ASSERT( connect ( this, SIGNAL ( MainWindowLoaded() ), this, SLOT ( WindowLoaded() ),
Qt::ConnectionType ( Qt::QueuedConnection | Qt::UniqueConnection ) ));This is not perfect as the event might be sent multiple times etc but worked fine for my use case.
full sample here
https://stackoverflow.com/questions/14356121/how-to-call-function-after-window-is-shown -
Hi :-)
I have a program that takes one command line parameter (the file to load). If something goes wrong while loading the file, a
QMessageBoxis shown. It's not placed correctly (not centered on theMainWindow), most probably because theshow()process is not finished yet when the load function is called.Here's a minimalistic example for producing the problem (at least on Linux/KDE):
main.cpp:
#include "MainWindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication app(argc, argv); MainWindow mainWindow; mainWindow.show(); mainWindow.loadTournament(); return app.exec(); }MainWindow.h:
#include <QMainWindow> class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(); void loadTournament(); };MainWindow.cpp:
#include "MainWindow.h" #include <QMessageBox> MainWindow::MainWindow() { resize(900, 700); } void MainWindow::loadTournament() { QMessageBox::critical(this, tr("foo"), tr("bar"), QMessageBox::Ok); }I tried to add
QApplication::processEvents();before the load function call, but it doesn't change anything.I also tried to add
QStringList arguments = QCoreApplication::arguments(); if (arguments.count() > 1) { loadTournament(arguments[1]); }to the end of the main window's constructor, but the behavior is exactly the same, also with a
QApplication::processEvents();before.I then tried to use a
QTimerwith the following code added to the end of the constructor:QTimer::singleShot(0, this, &MainWindow::checkLoadTournament);and
void MainWindow::checkLoadTournament() { QStringList arguments = QCoreApplication::arguments(); if (arguments.count() > 1) { loadTournament(arguments[1]); } }added. This also produces the very same wrong placement of the
QMessageBox.If I increase the
QTimerwait value (to e. g. 100 msecs), it works. But this seems a bit hacky to me, because I can't be sure if the main window is actually shown within this period of time.Is there a way to either know if the main window showing and placement is done and finished correctly and wait for this to be done before showing the
QMessageBoxor to place it to the right position before?Thanks in advance for all help!
@l3u_ said in QMessageBox is not positioned correctly when shown during startup:
void MainWindow::loadTournament()
{
QMessageBox::critical(this, tr("foo"), tr("bar"), QMessageBox::Ok);
}try replace this = 0;
QMessageBox::critical(0, tr("foo"), tr("bar"), QMessageBox::Ok); -
@mrjj I also tried to put the code inside the MainWindow's
showEventat the end, but even this did not make the message box appear at the right position … -
@l3u_ said in QMessageBox is not positioned correctly when shown during startup:
void MainWindow::loadTournament()
{
QMessageBox::critical(this, tr("foo"), tr("bar"), QMessageBox::Ok);
}try replace this = 0;
QMessageBox::critical(0, tr("foo"), tr("bar"), QMessageBox::Ok); -
@l3u_
hi
but you do it directly in event func.
Its not finished happening yet
I do via eventloop and just tested
with QMessageBox::critical does show centered.@mrjj Okay, when doing it via a signal, I could know when the window is set up completely. But how could I do the actual function call? Using a timer that checks periodically if some variable is set to true by the slot called after the show event? I mean, I don't want to call the load function always when the window is shown, but only if it's requested on the command line!
-
Hi,
Just a quick note: never put any function all in a Q_ASSERT or a classic assert expression. The function will never be called in release mode. Store the result of the function and assert on that.
-
@mrjj Okay, when doing it via a signal, I could know when the window is set up completely. But how could I do the actual function call? Using a timer that checks periodically if some variable is set to true by the slot called after the show event? I mean, I don't want to call the load function always when the window is shown, but only if it's requested on the command line!
@l3u_
Hi
Mine is like thisctor.. Q_ASSERT( connect ( this, SIGNAL ( MainWindowLoaded() ), this, SLOT ( WindowLoaded() ), Qt::ConnectionType ( Qt::QueuedConnection | Qt::UniqueConnection ) )); void MainWindow::showEvent ( QShowEvent* ev ) { QMainWindow::showEvent ( ev ); emit MainWindowLoaded(); } // the slot do thestuff void MainWindow::WindowLoaded() { real stuffHowever, as m.sue says, one shot timer is might just be cleaner for you :)
-
@l3u_
Hi
Mine is like thisctor.. Q_ASSERT( connect ( this, SIGNAL ( MainWindowLoaded() ), this, SLOT ( WindowLoaded() ), Qt::ConnectionType ( Qt::QueuedConnection | Qt::UniqueConnection ) )); void MainWindow::showEvent ( QShowEvent* ev ) { QMainWindow::showEvent ( ev ); emit MainWindowLoaded(); } // the slot do thestuff void MainWindow::WindowLoaded() { real stuffHowever, as m.sue says, one shot timer is might just be cleaner for you :)
@mrjj said in QMessageBox is not positioned correctly when shown during startup:
However, as m.sue says, one shot timer is might just be cleaner for you :)
I also think so, but what is the reason that the One-Shot-Timer with 0 delay does not change the result whereas the one with 100 ms delay causes the message box to be positionned correctly? Or asking the other way: what delay should I choose to be sure that the main window is always setup completely?
-
@mrjj said in QMessageBox is not positioned correctly when shown during startup:
However, as m.sue says, one shot timer is might just be cleaner for you :)
I also think so, but what is the reason that the One-Shot-Timer with 0 delay does not change the result whereas the one with 100 ms delay causes the message box to be positionned correctly? Or asking the other way: what delay should I choose to be sure that the main window is always setup completely?
-
@mrjj said in QMessageBox is not positioned correctly when shown during startup:
However, as m.sue says, one shot timer is might just be cleaner for you :)
I also think so, but what is the reason that the One-Shot-Timer with 0 delay does not change the result whereas the one with 100 ms delay causes the message box to be positionned correctly? Or asking the other way: what delay should I choose to be sure that the main window is always setup completely?