QMessageBox losing focus when created in the constructor of a class
-
Hello community! I am a relatively new Qt user and am currently working on an embedded project that was developed in Qt4 and ported to Qt5. I have come across some instances of QMessageBoxes (in my case a subclass of QMessageBox) being created in the constructor of another class that lose focus such that there is no way to accept or interact with it making me think that although the message box dialog is on top of everything else, the focus does not follow.
For a bit more background, the display of this device is mounted the wrong way up by design; I believe in Qt4 the orientation of the screen was being set from the app but now I use a viewport and scene method as per this topic https://forum.qt.io/topic/22852/qt-5-embedded-screen-rotation/13 .
Now the way the app manages the screens is as such: all screens inherit from QFrame and there is a CANVAS that holds the screens; the CANVAS is the only widget in the scene and the viewport is of the same size as the screen (we use it just for the rotation feature). Again, I am still trying to understand Qt but from what I can tell, the canvas holds the main widget (ScreenBase) which handles its own QVBoxLayout with setScreenWidget.
class ScreenBasePrivate : public QFrame { void setScreenWidget(QWidget* widget); } class ScreenBase : public QWidget { void setScreenWidget(QWidget* widget); private: ScreenBasePrivate * m_d; } void ScreenBase::setScreenWidget(QWidget* widget) { m_d->setScreenWidget(QWidget* widget); } void ScreenBasePrivate::setScreenWidget(QWidget* widget) { while (QLayoutItem* item = m_ui.screensLayout->itemAt(0)) { m_ui.screensLayout->removeItem(item); } m_ui.screensLayout->addWidget(widget); }
As an example, if I press a certain key on the device to go to another screen, from what I understand, this is what happens:
-new screen class is instantiated with CANVAS as its parent;
-new screen also is dependent on a QFrame class that represents the visual aspects of that screen which is then fed into that QVBoxLayout manager function;The actual constructor of the new screen:
NewScreen::NewScreen(QWidget* parent) : ScreenBase(parent), m_d(new NewScreenPrivate(this)) { setScreenWidget(m_d); //do some other stuff MyQMessageBox msgBox(CANVAS); //create messagebox here, setup title, text, etc.. msgBox.exec(); }
where NewScreenPrivate inherits from QFrame and has a private member UI_NewScreen which comes from the .h file generated by QtDesigner. This class always call setupUi(QFrame *) first in its own constructor.
In the example, when msgBox pops up, the focus is lost and I cannot select the dialog options or close the box. I have noticed that this never happens if the box pops up after the constructor finishes or after screen.exec() is called (unsure about this one). This did not used to happen in Qt4 but I expect the viewport is to blame for this.
If anyone could guide me through this and help me understand a bit more on the matter I would be eternally grateful! Apologies for the hard read and inexperience! Looking forward to some replies, thank you in advance!
-
Hello community! I am a relatively new Qt user and am currently working on an embedded project that was developed in Qt4 and ported to Qt5. I have come across some instances of QMessageBoxes (in my case a subclass of QMessageBox) being created in the constructor of another class that lose focus such that there is no way to accept or interact with it making me think that although the message box dialog is on top of everything else, the focus does not follow.
For a bit more background, the display of this device is mounted the wrong way up by design; I believe in Qt4 the orientation of the screen was being set from the app but now I use a viewport and scene method as per this topic https://forum.qt.io/topic/22852/qt-5-embedded-screen-rotation/13 .
Now the way the app manages the screens is as such: all screens inherit from QFrame and there is a CANVAS that holds the screens; the CANVAS is the only widget in the scene and the viewport is of the same size as the screen (we use it just for the rotation feature). Again, I am still trying to understand Qt but from what I can tell, the canvas holds the main widget (ScreenBase) which handles its own QVBoxLayout with setScreenWidget.
class ScreenBasePrivate : public QFrame { void setScreenWidget(QWidget* widget); } class ScreenBase : public QWidget { void setScreenWidget(QWidget* widget); private: ScreenBasePrivate * m_d; } void ScreenBase::setScreenWidget(QWidget* widget) { m_d->setScreenWidget(QWidget* widget); } void ScreenBasePrivate::setScreenWidget(QWidget* widget) { while (QLayoutItem* item = m_ui.screensLayout->itemAt(0)) { m_ui.screensLayout->removeItem(item); } m_ui.screensLayout->addWidget(widget); }
As an example, if I press a certain key on the device to go to another screen, from what I understand, this is what happens:
-new screen class is instantiated with CANVAS as its parent;
-new screen also is dependent on a QFrame class that represents the visual aspects of that screen which is then fed into that QVBoxLayout manager function;The actual constructor of the new screen:
NewScreen::NewScreen(QWidget* parent) : ScreenBase(parent), m_d(new NewScreenPrivate(this)) { setScreenWidget(m_d); //do some other stuff MyQMessageBox msgBox(CANVAS); //create messagebox here, setup title, text, etc.. msgBox.exec(); }
where NewScreenPrivate inherits from QFrame and has a private member UI_NewScreen which comes from the .h file generated by QtDesigner. This class always call setupUi(QFrame *) first in its own constructor.
In the example, when msgBox pops up, the focus is lost and I cannot select the dialog options or close the box. I have noticed that this never happens if the box pops up after the constructor finishes or after screen.exec() is called (unsure about this one). This did not used to happen in Qt4 but I expect the viewport is to blame for this.
If anyone could guide me through this and help me understand a bit more on the matter I would be eternally grateful! Apologies for the hard read and inexperience! Looking forward to some replies, thank you in advance!
@Robert_RT said in QMessageBox losing focus when created in the constructor of a class:
MyQMessageBox msgBox(CANVAS);
What is CANVAS and where is it initialised?
-
Canvas is another class that inherits from QFrame and is a sigleton created in main as such:
Canvas w(0, Qt::CustomizeWindowHint | Qt::FramelessWindowHint); w.setGeometry(0,0, 478, 270); #ifdef Q5_SCREEN_180 Scene* scene = new Scene(); Viewport* view = new Viewport(); #endif #ifdef Q5_SCREEN_180 view->setGeometry(0,0,482,274); view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); scene->addWidget(&w); view->setScene(scene); view->show(); view->rotate(180); #else w.show(); #endif
Thank you for your reply!
-
A bit of an update for anyone interested: because we are using a viewport and scene mechanism to rotate the screen, all the pop-up widgets such as message boxes are handled via QGraphicsProxyWidget. Looking through an event filter I can notice the focus going from my message box (proxy'd) to a QWidget(0x0) then to a QFrame (proxy'd). To get around this I captured the moment where the messagebox loses focus, got a pointer to the respective QGraphicsItem via the Scene singleton focusItem method, and later re-focused on that.
This is a workaround and I expect to get issues with this at some point. If anybody could explain more on the matter or give me some other pointers that would be greatly appreciated. Thank you!