Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. QMessageBox losing focus when created in the constructor of a class
Qt 6.11 is out! See what's new in the release blog

QMessageBox losing focus when created in the constructor of a class

Scheduled Pinned Locked Moved Unsolved Mobile and Embedded
4 Posts 2 Posters 646 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    Robert_RT
    wrote on last edited by
    #1

    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!

    jsulmJ 1 Reply Last reply
    0
    • R Robert_RT

      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!

      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by
      #2

      @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?

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      1
      • R Offline
        R Offline
        Robert_RT
        wrote on last edited by
        #3

        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!

        1 Reply Last reply
        0
        • R Offline
          R Offline
          Robert_RT
          wrote on last edited by
          #4

          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!

          1 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved