Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QMessageBox show() not displaying text
QtWS25 Last Chance

QMessageBox show() not displaying text

Scheduled Pinned Locked Moved Solved General and Desktop
25 Posts 6 Posters 12.1k Views
  • 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.
  • mzimmersM Offline
    mzimmersM Offline
    mzimmers
    wrote on last edited by
    #1

    Hi all -

    I need to inform the user that the device he's working on is temporarily unavailable. I'm trying to use a QMessageBox. This is the code:

            // ??? wait for debug messages to start before continuing.
            QMessageBox messageBox;
            messageBox.setText("Please wait while the target resets.");
    //        messageBox.setModal(true);
    //        messageBox.show();
            messageBox.exec();
    
            bool b = serial->waitForReadyRead(10000);
            sendDiscoveryRequest();
    
            messageBox.done(0);
    

    This doesn't work as I want, because the exec() call doesn't return. But the message box looks fine. When I disable the exec() call, and use the setModal/show calls, the behavior is good, but my message box is empty (doesn't have the text or the OK button). Any idea why?

    If there's a better method for doing this, I'm open to suggestion. The only requirement is that the message should be dismissable either by the user, or by the program.

    VRoninV J.HilkJ 2 Replies Last reply
    0
    • mzimmersM mzimmers

      Hi all -

      I need to inform the user that the device he's working on is temporarily unavailable. I'm trying to use a QMessageBox. This is the code:

              // ??? wait for debug messages to start before continuing.
              QMessageBox messageBox;
              messageBox.setText("Please wait while the target resets.");
      //        messageBox.setModal(true);
      //        messageBox.show();
              messageBox.exec();
      
              bool b = serial->waitForReadyRead(10000);
              sendDiscoveryRequest();
      
              messageBox.done(0);
      

      This doesn't work as I want, because the exec() call doesn't return. But the message box looks fine. When I disable the exec() call, and use the setModal/show calls, the behavior is good, but my message box is empty (doesn't have the text or the OK button). Any idea why?

      If there's a better method for doing this, I'm open to suggestion. The only requirement is that the message should be dismissable either by the user, or by the program.

      VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by VRonin
      #2

      I'm surprised it's shown at all. serial->waitForReadyRead(10000); blocks the event loop and if you return from that method (to the event loop) the messagebox is deleted.

      QMessageBox* messageBox=new QMessageBox(this);
      messageBox->setText("Please wait while the target resets.");
      connect(serial,SIGNAL(readyRead()),this,SLOT(sendDiscoveryRequest()));
      connect(serial,SIGNAL(readyRead()),messageBox,SLOT(deleteLater()));
      messageBox->show();
      

      P.S.
      if you want connect(serial,SIGNAL(readyRead()),this,SLOT(sendDiscoveryRequest())); to disconnect when messagebox is closed you can use Qt5 connection syntax, use messageBox as context and a lambda [this]()->void{sendDiscoveryRequest();} as slot

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      mzimmersM 1 Reply Last reply
      4
      • VRoninV VRonin

        I'm surprised it's shown at all. serial->waitForReadyRead(10000); blocks the event loop and if you return from that method (to the event loop) the messagebox is deleted.

        QMessageBox* messageBox=new QMessageBox(this);
        messageBox->setText("Please wait while the target resets.");
        connect(serial,SIGNAL(readyRead()),this,SLOT(sendDiscoveryRequest()));
        connect(serial,SIGNAL(readyRead()),messageBox,SLOT(deleteLater()));
        messageBox->show();
        

        P.S.
        if you want connect(serial,SIGNAL(readyRead()),this,SLOT(sendDiscoveryRequest())); to disconnect when messagebox is closed you can use Qt5 connection syntax, use messageBox as context and a lambda [this]()->void{sendDiscoveryRequest();} as slot

        mzimmersM Offline
        mzimmersM Offline
        mzimmers
        wrote on last edited by mzimmers
        #3

        @VRonin thank you for the code fragment. It doesn't seem to be working quite right yet...the sendDiscoveryRequest() slot never seems to get called. Any idea what might be blocking its delivery?

        As clarification for what I'm trying to do, when I enter this code, I need the application to "sleep" until readyRead() is called. This is true whether or not the user dismisses the message box.

        EDIT: please disregard the first paragraph. I'd forgot to re-declare sendDiscoveryRequest() as a slot.

        jsulmJ 1 Reply Last reply
        0
        • mzimmersM mzimmers

          @VRonin thank you for the code fragment. It doesn't seem to be working quite right yet...the sendDiscoveryRequest() slot never seems to get called. Any idea what might be blocking its delivery?

          As clarification for what I'm trying to do, when I enter this code, I need the application to "sleep" until readyRead() is called. This is true whether or not the user dismisses the message box.

          EDIT: please disregard the first paragraph. I'd forgot to re-declare sendDiscoveryRequest() as a slot.

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

          @mzimmers Why does your app need to "sleep"? Your app already has an event loop, so the slot will be called as soon as the signal is emitted.

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

          mzimmersM 1 Reply Last reply
          1
          • jsulmJ jsulm

            @mzimmers Why does your app need to "sleep"? Your app already has an event loop, so the slot will be called as soon as the signal is emitted.

            mzimmersM Offline
            mzimmersM Offline
            mzimmers
            wrote on last edited by
            #5

            @jsulm The target device, upon receiving a particular command, sends a response to me and then goes into a reset mode. During the first ~10 seconds of this reset mode, the device goes completely silent and accepts no input. After this initial period, the device begins transmitting status messages and will accept certain commands. For another ~30 seconds, the device "appears" active, but is still not capable of accepting all commands.

            I want my app to wait for the end of the initial (10 second) period by remaining idle until it receives the first of those status messages. I also want to alert the user that during this period, none of his commands will work.

            Incidentally, there's a problem with VRonin's above solution: I don't want to send a discovery request to every read, because 1) the reads are buffered and I don't always get a complete message and 2) some of the reads call for different requests to go out. This is handled elsewhere in the program.

            1 Reply Last reply
            0
            • mzimmersM mzimmers

              Hi all -

              I need to inform the user that the device he's working on is temporarily unavailable. I'm trying to use a QMessageBox. This is the code:

                      // ??? wait for debug messages to start before continuing.
                      QMessageBox messageBox;
                      messageBox.setText("Please wait while the target resets.");
              //        messageBox.setModal(true);
              //        messageBox.show();
                      messageBox.exec();
              
                      bool b = serial->waitForReadyRead(10000);
                      sendDiscoveryRequest();
              
                      messageBox.done(0);
              

              This doesn't work as I want, because the exec() call doesn't return. But the message box looks fine. When I disable the exec() call, and use the setModal/show calls, the behavior is good, but my message box is empty (doesn't have the text or the OK button). Any idea why?

              If there's a better method for doing this, I'm open to suggestion. The only requirement is that the message should be dismissable either by the user, or by the program.

              J.HilkJ Offline
              J.HilkJ Offline
              J.Hilk
              Moderators
              wrote on last edited by
              #6

              @mzimmers

              Try this one:

              QTime t;
              t.start();
              QMessageBox messageBox;
              messageBox.setText("Please wait while the target resets.");
              
              messageBox.exec();
              
              bool b = serial->waitForReadyRead(10000- t.elapsed() > 10000 ? 10000 : t.elapsed());
              sendDiscoveryRequest();
              

              QMessageBox::exec is a blocking call, so everything after the call is executed when the MessageBox is closed. But the Qtime element will still run.

              If you want to automatically close the dialog box after 10 seconds, to resume your program, thats more complicated.


              Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


              Q: What's that?
              A: It's blue light.
              Q: What does it do?
              A: It turns blue.

              mzimmersM 1 Reply Last reply
              0
              • J.HilkJ J.Hilk

                @mzimmers

                Try this one:

                QTime t;
                t.start();
                QMessageBox messageBox;
                messageBox.setText("Please wait while the target resets.");
                
                messageBox.exec();
                
                bool b = serial->waitForReadyRead(10000- t.elapsed() > 10000 ? 10000 : t.elapsed());
                sendDiscoveryRequest();
                

                QMessageBox::exec is a blocking call, so everything after the call is executed when the MessageBox is closed. But the Qtime element will still run.

                If you want to automatically close the dialog box after 10 seconds, to resume your program, thats more complicated.

                mzimmersM Offline
                mzimmersM Offline
                mzimmers
                wrote on last edited by
                #7

                @J.Hilk yeah, ideally the message would self-dismiss when the device reset has completed. Perhaps I shouldn't be using a message box (or any dialog) for this, but should be indicating this in the UI itself?

                J.HilkJ kshegunovK 2 Replies Last reply
                0
                • mzimmersM mzimmers

                  @J.Hilk yeah, ideally the message would self-dismiss when the device reset has completed. Perhaps I shouldn't be using a message box (or any dialog) for this, but should be indicating this in the UI itself?

                  J.HilkJ Offline
                  J.HilkJ Offline
                  J.Hilk
                  Moderators
                  wrote on last edited by J.Hilk
                  #8

                  @mzimmers
                  of course, idealy creating your own "Custom MessageBox" is the way I would go, and have gone in the past.

                  However if you're feeling lazy, you can try this, its untested, but should work.

                  QTime t;   
                  t.start();
                  QMessageBox messageBox;
                  messageBox.setText("Please wait while the target resets.");
                  
                  QTimer::singleShot(10000, &messageBox, QMessageBox::close);
                  messageBox.exec();
                  
                  bool b = serial->waitForReadyRead(10000- t.elapsed() > 10000 ? 10000 : t.elapsed());
                  sendDiscoveryRequest();
                  

                  Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                  Q: What's that?
                  A: It's blue light.
                  Q: What does it do?
                  A: It turns blue.

                  1 Reply Last reply
                  1
                  • mzimmersM mzimmers

                    @J.Hilk yeah, ideally the message would self-dismiss when the device reset has completed. Perhaps I shouldn't be using a message box (or any dialog) for this, but should be indicating this in the UI itself?

                    kshegunovK Offline
                    kshegunovK Offline
                    kshegunov
                    Moderators
                    wrote on last edited by
                    #9

                    @mzimmers said in QMessageBox show() not displaying text:

                    yeah, ideally the message would self-dismiss when the device reset has completed. Perhaps I shouldn't be using a message box (or any dialog) for this, but should be indicating this in the UI itself?

                    What you need in fact is a state machine to represent the device's states and to notify you in an asynchronous fashion of state changes. Then you can tie those signals to your dialog or UI or w/e.

                    Read and abide by the Qt Code of Conduct

                    mzimmersM 1 Reply Last reply
                    4
                    • kshegunovK kshegunov

                      @mzimmers said in QMessageBox show() not displaying text:

                      yeah, ideally the message would self-dismiss when the device reset has completed. Perhaps I shouldn't be using a message box (or any dialog) for this, but should be indicating this in the UI itself?

                      What you need in fact is a state machine to represent the device's states and to notify you in an asynchronous fashion of state changes. Then you can tie those signals to your dialog or UI or w/e.

                      mzimmersM Offline
                      mzimmersM Offline
                      mzimmers
                      wrote on last edited by
                      #10

                      @kshegunov funny you should mention that -- I was just coming to the same realization. Now I have to decide whether I need a full blown state machine, or if I can just fake it with a member variable in the device object that is set by the worker upon various occurrences.

                      I'd just finished writing this when you posted:

                      enum DevStates
                      {
                          UNKNOWN,        // this value used when the app starts
                          RUNNING,        // this is the "normal" state
                                          // entered after receiving a discovery response
                                          // exits after receiving a change confirmation
                          WAITING,        // the device enters this state upon receiving
                                          // a change command (and sending a response)
                                          // exits this state after a ~5 second timeout
                          RESETTING       // the device enters this state after the timeout
                                          // exits when it responds to a disovery request.
                      };
                      
                      kshegunovK 1 Reply Last reply
                      0
                      • mzimmersM mzimmers

                        @kshegunov funny you should mention that -- I was just coming to the same realization. Now I have to decide whether I need a full blown state machine, or if I can just fake it with a member variable in the device object that is set by the worker upon various occurrences.

                        I'd just finished writing this when you posted:

                        enum DevStates
                        {
                            UNKNOWN,        // this value used when the app starts
                            RUNNING,        // this is the "normal" state
                                            // entered after receiving a discovery response
                                            // exits after receiving a change confirmation
                            WAITING,        // the device enters this state upon receiving
                                            // a change command (and sending a response)
                                            // exits this state after a ~5 second timeout
                            RESETTING       // the device enters this state after the timeout
                                            // exits when it responds to a disovery request.
                        };
                        
                        kshegunovK Offline
                        kshegunovK Offline
                        kshegunov
                        Moderators
                        wrote on last edited by
                        #11

                        @mzimmers said in QMessageBox show() not displaying text:

                        Now I have to decide whether I need a full blown state machine, or if I can just fake it with a member variable in the device object that is set by the worker upon various occurrences.

                        The latter is the former. :)
                        The simplest state machine is an ordinary switch (or if-else cascade) which modifies a "state" variable depending on the input you feed it. You'd feed the different messages/or hw events you get into the machine and it'd reflect that in the state.

                        Read and abide by the Qt Code of Conduct

                        1 Reply Last reply
                        1
                        • mrjjM Offline
                          mrjjM Offline
                          mrjj
                          Lifetime Qt Champion
                          wrote on last edited by
                          #12

                          Hi
                          Since you only have one device with few States,
                          switch case will work pretty well as
                          something like
                          http://digint.ch/tinyfsm/doc/introduction.html
                          is most likely overkill for such simple machine.
                          (Qt also have http://doc.qt.io/qt-5/qstate.html#details )

                          However, an object orientated approach makes it easier to add test code and extra conditions
                          on transit and will in general be more solid with future features added.

                          but in my experience, if only a few states and few possible paths, a switch case and
                          function to handle the transits is just right as using a Full State system is pretty verbose.

                          mzimmersM 1 Reply Last reply
                          2
                          • mrjjM mrjj

                            Hi
                            Since you only have one device with few States,
                            switch case will work pretty well as
                            something like
                            http://digint.ch/tinyfsm/doc/introduction.html
                            is most likely overkill for such simple machine.
                            (Qt also have http://doc.qt.io/qt-5/qstate.html#details )

                            However, an object orientated approach makes it easier to add test code and extra conditions
                            on transit and will in general be more solid with future features added.

                            but in my experience, if only a few states and few possible paths, a switch case and
                            function to handle the transits is just right as using a Full State system is pretty verbose.

                            mzimmersM Offline
                            mzimmersM Offline
                            mzimmers
                            wrote on last edited by
                            #13

                            @mrjj thanks for the link. I tend to agree that for this program, a true state machine is overkill (though I will probably need one in a few weeks on another project). This project has been a learning experience for me on a few levels: it's really the first time I've tried to do anything with Qt, it's my first attempt at OOD and I'm using some data structures for the first time. Lots of opportunity for mistakes.

                            Currently I'm trying to run a timer at most once a second. Here's a code fragment:

                                        if (devState == RESETTING)
                                        {
                                            if (timer.isActive()) // only do one at a time.
                                            {
                                                qDebug() << "\t\ttimer already queued.";
                                            }
                                            else
                                            {
                                                timer.singleShot(1000, this, SLOT(sendDiscoveryRequest()));
                                                qDebug() << "\t\tqueueing timer.";
                                            }
                                        }
                            

                            This code is inside a slot function that is called whenever the target writes to the host. I never hit the "timer already queued". Am I misusing the singleshot feature?

                            mrjjM 1 Reply Last reply
                            0
                            • mzimmersM mzimmers

                              @mrjj thanks for the link. I tend to agree that for this program, a true state machine is overkill (though I will probably need one in a few weeks on another project). This project has been a learning experience for me on a few levels: it's really the first time I've tried to do anything with Qt, it's my first attempt at OOD and I'm using some data structures for the first time. Lots of opportunity for mistakes.

                              Currently I'm trying to run a timer at most once a second. Here's a code fragment:

                                          if (devState == RESETTING)
                                          {
                                              if (timer.isActive()) // only do one at a time.
                                              {
                                                  qDebug() << "\t\ttimer already queued.";
                                              }
                                              else
                                              {
                                                  timer.singleShot(1000, this, SLOT(sendDiscoveryRequest()));
                                                  qDebug() << "\t\tqueueing timer.";
                                              }
                                          }
                              

                              This code is inside a slot function that is called whenever the target writes to the host. I never hit the "timer already queued". Am I misusing the singleshot feature?

                              mrjjM Offline
                              mrjjM Offline
                              mrjj
                              Lifetime Qt Champion
                              wrote on last edited by
                              #14

                              Hi
                              Normally you use the static version of singleshot

                              QTimer::singleShot(1000, this, SLOT(timerDone()));

                              It requires no instance.

                              But seems you need an instance for others checks so a variable should be fine.

                              so when u send DiscoveryRequest, can it also timeout ?

                              mzimmersM 1 Reply Last reply
                              0
                              • mrjjM mrjj

                                Hi
                                Normally you use the static version of singleshot

                                QTimer::singleShot(1000, this, SLOT(timerDone()));

                                It requires no instance.

                                But seems you need an instance for others checks so a variable should be fine.

                                so when u send DiscoveryRequest, can it also timeout ?

                                mzimmersM Offline
                                mzimmersM Offline
                                mzimmers
                                wrote on last edited by
                                #15

                                @mrjj are you asking if the sendDiscoveryRequest() routine might be timing out? That's unlikely...it just writes a short byte array to the serial port and flushes it.

                                mrjjM 1 Reply Last reply
                                0
                                • mzimmersM mzimmers

                                  @mrjj are you asking if the sendDiscoveryRequest() routine might be timing out? That's unlikely...it just writes a short byte array to the serial port and flushes it.

                                  mrjjM Offline
                                  mrjjM Offline
                                  mrjj
                                  Lifetime Qt Champion
                                  wrote on last edited by
                                  #16

                                  @mzimmers
                                  Oh, sorry for being unclear,
                                  i mean, do u need to be able to have a timeout on each command if no answer is received ?
                                  Often it goes
                                  SendCMD
                                  OnReplyDo/ TimeOut-> restart sequence.

                                  mzimmersM 1 Reply Last reply
                                  0
                                  • mrjjM mrjj

                                    @mzimmers
                                    Oh, sorry for being unclear,
                                    i mean, do u need to be able to have a timeout on each command if no answer is received ?
                                    Often it goes
                                    SendCMD
                                    OnReplyDo/ TimeOut-> restart sequence.

                                    mzimmersM Offline
                                    mzimmersM Offline
                                    mzimmers
                                    wrote on last edited by
                                    #17

                                    @mrjj I'm still not sure I understand your question, so let me give some supplementary information.

                                    In normal operation, the host forms requests and sends them to the target, then reads a response from the target. Unfortunately, the target also spews out unsolicited (and unwanted messages) when in a certain state. During the first 10-15 seconds of this state, the target will ignore any input from the host. After this 10-15 second period, the target will listen for requests. A discovery request will cause the target to cease sending the (unwanted) debug messages.

                                    Because the messages are binary and encrypted, there's no way of knowing at first glance whether I've received a "real" response, or just the debugger output. My solution is, when the target is in the "resetting" state, send it a discovery request every second, until I get a valid discovery response. THAT is what I'm trying to do with my timer.

                                    I don't "wait" for responses to my requests; I just process any serial input with a slot.

                                    I don't know whether this answers your question or not...

                                    mrjjM 1 Reply Last reply
                                    1
                                    • mzimmersM mzimmers

                                      @mrjj I'm still not sure I understand your question, so let me give some supplementary information.

                                      In normal operation, the host forms requests and sends them to the target, then reads a response from the target. Unfortunately, the target also spews out unsolicited (and unwanted messages) when in a certain state. During the first 10-15 seconds of this state, the target will ignore any input from the host. After this 10-15 second period, the target will listen for requests. A discovery request will cause the target to cease sending the (unwanted) debug messages.

                                      Because the messages are binary and encrypted, there's no way of knowing at first glance whether I've received a "real" response, or just the debugger output. My solution is, when the target is in the "resetting" state, send it a discovery request every second, until I get a valid discovery response. THAT is what I'm trying to do with my timer.

                                      I don't "wait" for responses to my requests; I just process any serial input with a slot.

                                      I don't know whether this answers your question or not...

                                      mrjjM Offline
                                      mrjjM Offline
                                      mrjj
                                      Lifetime Qt Champion
                                      wrote on last edited by
                                      #18

                                      @mzimmers
                                      Yes that a very nice explanation.
                                      Its seems like a valid approach.
                                      Sometimes i use a list of small classes to hold each state, and use
                                      virtual function to make sure i dont get too many if structures

                                      But i wonder one thing
                                      timer.singleShot(1000, this, SLOT(sendDiscoveryRequest()));

                                      so you call sendDiscoveryRequest one time. will it then start the timer again?

                                      1 Reply Last reply
                                      1
                                      • mzimmersM Offline
                                        mzimmersM Offline
                                        mzimmers
                                        wrote on last edited by
                                        #19

                                        The sendDiscoveryMessage() call is a "kick start" to the communications process. One of two things will happen:

                                        • the target is in running state, and will respond with a valid response. In this case, no new timer is desired.
                                        • the target is in resetting state, and will not respond, BUT will continue to send those spurious debug messages. When it sends one of these, the routine the above code is in is invoked (as a slot).

                                        So, in either case, the host will receive some input from the target, and normal processing can continue.

                                        These debug messages can come very quickly, and I don't wish to respond to each with a discovery request. This is the purpose of the timer -- to "gate" my requests. But...it's not working, as timer.isActive() never returns true.

                                        mrjjM 1 Reply Last reply
                                        0
                                        • mzimmersM mzimmers

                                          The sendDiscoveryMessage() call is a "kick start" to the communications process. One of two things will happen:

                                          • the target is in running state, and will respond with a valid response. In this case, no new timer is desired.
                                          • the target is in resetting state, and will not respond, BUT will continue to send those spurious debug messages. When it sends one of these, the routine the above code is in is invoked (as a slot).

                                          So, in either case, the host will receive some input from the target, and normal processing can continue.

                                          These debug messages can come very quickly, and I don't wish to respond to each with a discovery request. This is the purpose of the timer -- to "gate" my requests. But...it's not working, as timer.isActive() never returns true.

                                          mrjjM Offline
                                          mrjjM Offline
                                          mrjj
                                          Lifetime Qt Champion
                                          wrote on last edited by mrjj
                                          #20

                                          @mzimmers

                                          • timer.isActive() never returns true.
                                            Well if it takes more than 1 sec before the containing slot is called again then is it then not true that timer.isActive() is false?
                                            also the single shot might not even set active. maybe only start() does.
                                            (just speculating)
                                          mzimmersM 1 Reply Last reply
                                          1

                                          • Login

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