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. Question about show() hide()
Forum Updated to NodeBB v4.3 + New Features

Question about show() hide()

Scheduled Pinned Locked Moved Solved General and Desktop
17 Posts 7 Posters 1.3k Views 4 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.
  • JonBJ JonB

    @Quiccz
    I don't think calling show/hide() enters/raises those events at the time you call them. It merely marks a widget as to be shown or hidden. Events don't get raised until that actually happens (from the event loop).

    Normally you do not need to show/hide child widgets: showing/hiding a parent widget takes child widgets with it.

    When showing one of a number of widgets (parent1 or parent2) you might like to use QStackedWidget instead of manually managing show/hide()s yourself.

    I don't think this has anything to do with any time it might take to e.g. load an image, I don't think that happens when you call show/hide(). It only happens when the image is actually shown, I think. I don't know if there is a way/call to make it so the images are all preloaded so that they show any faster when called for, there might be.

    Q Offline
    Q Offline
    Quiccz
    wrote on last edited by Quiccz
    #4

    @JonB I write a demo.

    #ifndef PICWIDGET_H
    #define PICWIDGET_H
    
    #include <QMainWindow>
    #include <QLabel>
    class PicWidget : public QWidget
    {
        Q_OBJECT
    
    public:
        PicWidget(QWidget *parent = nullptr);
        ~PicWidget();
        void setPic(QString file);
        void paintEvent(QPaintEvent* event) override;
        void showEvent(QShowEvent* event) override;
        void hideEvent(QHideEvent* event) override;
    
    
    private:
        QLabel* m_label;
    };
    #endif // PICWIDGET_H
    
    
    #include "picwidget.h"
    
    PicWidget::PicWidget(QWidget *parent)
        : QWidget(parent)
    {
    }
    
    PicWidget::~PicWidget()
    {
    }
    
    void PicWidget::showEvent(QShowEvent* event)
    {
        QWidget::showEvent(event);
        qDebug() << "pic show event";
    }
    
    void PicWidget::paintEvent(QPaintEvent* event)
    {
        QWidget::paintEvent(event);
        qDebug() << "pic paint event";
    }
    
    void PicWidget::hideEvent(QHideEvent* event)
    {
        QWidget::hideEvent(event);
        qDebug() << "pic hide event";
    }
    
    void PicWidget::setPic(QString file)
    {
        m_label = new QLabel(this);
        QImage img = QImage(file);
        m_label->setPixmap(QPixmap::fromImage(img));
        m_label->show();
    }
    
    
    #ifndef PARENTWIDGET_H
    #define PARENTWIDGET_H
    #include <QWidget>
    #include "picwidget.h"
    class ParentWidget : public QWidget
    {
    public:
        ParentWidget(QWidget* parent = nullptr);
        void paintEvent(QPaintEvent* event) override;
        void showEvent(QShowEvent* event) override;
        void hideEvent(QHideEvent* event) override;
        void showAll();
        void hideAll();
    private:
        QVector<PicWidget*> pics;
    };
    
    #endif // PARENTWIDGET_H
    
    
    #include "parentwidget.h"
    
    ParentWidget::ParentWidget(QWidget* parent)
        : QWidget(parent)
    {
        for(int i = 0; i < 1; i++)
        {
            PicWidget* pic = new PicWidget(this);
            pic->setPic("D://test.png");
            pic->setGeometry(i*100, i*100, 100, 100);
            pics.push_back(pic);
        }
    }
    
    void ParentWidget::showAll()
    {
        for(int i = 0; i < pics.size(); i++)
        {
            pics[i]->show();
        }
    }
    
    void ParentWidget::hideAll()
    {
        for(int i = 0; i < pics.size(); i++)
        {
            pics[i]->hide();
        }
    }
    
    void ParentWidget::showEvent(QShowEvent* event)
    {
        QWidget::showEvent(event);
        qDebug() << "parent show event";
    }
    
    void ParentWidget::paintEvent(QPaintEvent* event)
    {
        QWidget::paintEvent(event);
        qDebug() << "parent paint event";
    }
    
    void ParentWidget::hideEvent(QHideEvent* event)
    {
        QWidget::hideEvent(event);
        qDebug() << "parent hide event";
    }
    
    
    #include "parentwidget.h"
    
    #include <QApplication>
    #include <QTimer>
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QMainWindow window;
        window.show();
        ParentWidget w1(&window);
        ParentWidget w2(&window);
        w1.setGeometry(0, 0, 300, 300);
        w2.setGeometry(0, 0, 300, 300);
        QTimer::singleShot(3000, [&](){
            qDebug() << "w1 showall";
            w1.showAll();
            qDebug() << "w1 show";
            w1.show();
            qDebug() << "w2 hide";
            w2.hide();
            qDebug() << "w2 hideall";
            w2.hideAll();
            qDebug() << "end1";
    
        });
    
        QTimer::singleShot(6000, [&](){
            qDebug() << "w2 showall";
            w2.showAll();
            qDebug() << "w2 show";
    
            w2.show();
            qDebug() << "w1 hide";
    
            w1.hide();
            qDebug() << "w1 hideall";
    
            w1.hideAll();
            qDebug() << "end2";
    
        });
        return a.exec();
    }
    
    

    Here is output
    5540ea54-a896-44b4-80de-af4b441020fe-image.png

    it seems pic parent paint first then pic paint.

    If i paint 10 pics, and add sleep in pic_paintevent, it will show all pics at same time after 10s.
    77508e41-a471-449f-ada3-3916fe2b9eba-image.png

    if parent show first, it will show all pics at same time after 10s, why?
    04377262-cbd7-4065-9048-b202ddd49146-image.png

    Pl45m4P 1 Reply Last reply
    0
    • Q Quiccz

      @JonB I write a demo.

      #ifndef PICWIDGET_H
      #define PICWIDGET_H
      
      #include <QMainWindow>
      #include <QLabel>
      class PicWidget : public QWidget
      {
          Q_OBJECT
      
      public:
          PicWidget(QWidget *parent = nullptr);
          ~PicWidget();
          void setPic(QString file);
          void paintEvent(QPaintEvent* event) override;
          void showEvent(QShowEvent* event) override;
          void hideEvent(QHideEvent* event) override;
      
      
      private:
          QLabel* m_label;
      };
      #endif // PICWIDGET_H
      
      
      #include "picwidget.h"
      
      PicWidget::PicWidget(QWidget *parent)
          : QWidget(parent)
      {
      }
      
      PicWidget::~PicWidget()
      {
      }
      
      void PicWidget::showEvent(QShowEvent* event)
      {
          QWidget::showEvent(event);
          qDebug() << "pic show event";
      }
      
      void PicWidget::paintEvent(QPaintEvent* event)
      {
          QWidget::paintEvent(event);
          qDebug() << "pic paint event";
      }
      
      void PicWidget::hideEvent(QHideEvent* event)
      {
          QWidget::hideEvent(event);
          qDebug() << "pic hide event";
      }
      
      void PicWidget::setPic(QString file)
      {
          m_label = new QLabel(this);
          QImage img = QImage(file);
          m_label->setPixmap(QPixmap::fromImage(img));
          m_label->show();
      }
      
      
      #ifndef PARENTWIDGET_H
      #define PARENTWIDGET_H
      #include <QWidget>
      #include "picwidget.h"
      class ParentWidget : public QWidget
      {
      public:
          ParentWidget(QWidget* parent = nullptr);
          void paintEvent(QPaintEvent* event) override;
          void showEvent(QShowEvent* event) override;
          void hideEvent(QHideEvent* event) override;
          void showAll();
          void hideAll();
      private:
          QVector<PicWidget*> pics;
      };
      
      #endif // PARENTWIDGET_H
      
      
      #include "parentwidget.h"
      
      ParentWidget::ParentWidget(QWidget* parent)
          : QWidget(parent)
      {
          for(int i = 0; i < 1; i++)
          {
              PicWidget* pic = new PicWidget(this);
              pic->setPic("D://test.png");
              pic->setGeometry(i*100, i*100, 100, 100);
              pics.push_back(pic);
          }
      }
      
      void ParentWidget::showAll()
      {
          for(int i = 0; i < pics.size(); i++)
          {
              pics[i]->show();
          }
      }
      
      void ParentWidget::hideAll()
      {
          for(int i = 0; i < pics.size(); i++)
          {
              pics[i]->hide();
          }
      }
      
      void ParentWidget::showEvent(QShowEvent* event)
      {
          QWidget::showEvent(event);
          qDebug() << "parent show event";
      }
      
      void ParentWidget::paintEvent(QPaintEvent* event)
      {
          QWidget::paintEvent(event);
          qDebug() << "parent paint event";
      }
      
      void ParentWidget::hideEvent(QHideEvent* event)
      {
          QWidget::hideEvent(event);
          qDebug() << "parent hide event";
      }
      
      
      #include "parentwidget.h"
      
      #include <QApplication>
      #include <QTimer>
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
          QMainWindow window;
          window.show();
          ParentWidget w1(&window);
          ParentWidget w2(&window);
          w1.setGeometry(0, 0, 300, 300);
          w2.setGeometry(0, 0, 300, 300);
          QTimer::singleShot(3000, [&](){
              qDebug() << "w1 showall";
              w1.showAll();
              qDebug() << "w1 show";
              w1.show();
              qDebug() << "w2 hide";
              w2.hide();
              qDebug() << "w2 hideall";
              w2.hideAll();
              qDebug() << "end1";
      
          });
      
          QTimer::singleShot(6000, [&](){
              qDebug() << "w2 showall";
              w2.showAll();
              qDebug() << "w2 show";
      
              w2.show();
              qDebug() << "w1 hide";
      
              w1.hide();
              qDebug() << "w1 hideall";
      
              w1.hideAll();
              qDebug() << "end2";
      
          });
          return a.exec();
      }
      
      

      Here is output
      5540ea54-a896-44b4-80de-af4b441020fe-image.png

      it seems pic parent paint first then pic paint.

      If i paint 10 pics, and add sleep in pic_paintevent, it will show all pics at same time after 10s.
      77508e41-a471-449f-ada3-3916fe2b9eba-image.png

      if parent show first, it will show all pics at same time after 10s, why?
      04377262-cbd7-4065-9048-b202ddd49146-image.png

      Pl45m4P Offline
      Pl45m4P Offline
      Pl45m4
      wrote on last edited by
      #5

      @Quiccz said in Question about show() hide():

      If i paint 10 pics, and add sleep in pic_paintevent, it will show all pics at same time after 10s.

      Don't let your GUI thread sleep. It's bad. You won't receive any events then.


      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

      ~E. W. Dijkstra

      Q 1 Reply Last reply
      1
      • Pl45m4P Pl45m4

        @Quiccz said in Question about show() hide():

        If i paint 10 pics, and add sleep in pic_paintevent, it will show all pics at same time after 10s.

        Don't let your GUI thread sleep. It's bad. You won't receive any events then.

        Q Offline
        Q Offline
        Quiccz
        wrote on last edited by Quiccz
        #6

        @Pl45m4 It is just a test, i try to figureout why my pics won't show together in my other project. But my demo show together. i thought it because paint pic need time, so i add sleep for test.
        ebfec6e9-956c-4a3e-8384-733a1a921d54-image.png
        result same.

        I try to add some event between pic paintevent and parent paintevent but failed.

        JonBJ 1 Reply Last reply
        0
        • Q Quiccz

          @Pl45m4 It is just a test, i try to figureout why my pics won't show together in my other project. But my demo show together. i thought it because paint pic need time, so i add sleep for test.
          ebfec6e9-956c-4a3e-8384-733a1a921d54-image.png
          result same.

          I try to add some event between pic paintevent and parent paintevent but failed.

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by JonB
          #7

          @Quiccz The above will just occupy/block the main thread.

          Q 1 Reply Last reply
          0
          • JonBJ JonB

            @Quiccz The above will just occupy/block the main thread.

            Q Offline
            Q Offline
            Quiccz
            wrote on last edited by Quiccz
            #8

            @JonB
            I know it will block the main thread. In another real project of mine, I also displayed multiple sub-widgets one by one, and then showed the parent widget. After that, I hid another parent widget, but the actual display sometimes showed 27 out of 30 images simultaneously, with the remaining three images appearing one by one. However, there were times when all 30 images would display together. I initially thought it was due to the time needed for painting high-resolution images in my paint event, so I used a for loop to simulate this time-consuming process. It takes about 10ms to paint each image. In the demo, even with a 1s delay, it does not result in displaying the images one by one; instead, all images are shown simultaneously after the paint event for each image completes.

            What I primarily want to know is whether there are any factors that could affect the order of display. I have been unable to identify the issue in my actual project.

            JoeCFDJ M 2 Replies Last reply
            0
            • Q Quiccz

              @JonB
              I know it will block the main thread. In another real project of mine, I also displayed multiple sub-widgets one by one, and then showed the parent widget. After that, I hid another parent widget, but the actual display sometimes showed 27 out of 30 images simultaneously, with the remaining three images appearing one by one. However, there were times when all 30 images would display together. I initially thought it was due to the time needed for painting high-resolution images in my paint event, so I used a for loop to simulate this time-consuming process. It takes about 10ms to paint each image. In the demo, even with a 1s delay, it does not result in displaying the images one by one; instead, all images are shown simultaneously after the paint event for each image completes.

              What I primarily want to know is whether there are any factors that could affect the order of display. I have been unable to identify the issue in my actual project.

              JoeCFDJ Offline
              JoeCFDJ Offline
              JoeCFD
              wrote on last edited by JoeCFD
              #9

              @Quiccz I guess paint events(in event loop) may not come one after another in a big app with a lot of running threads. And threads also access CPU randomly one after another. The main thread has some pause as well. Some other apps in the OS need to access CPU too.

              1 Reply Last reply
              0
              • Q Quiccz

                @JonB
                I know it will block the main thread. In another real project of mine, I also displayed multiple sub-widgets one by one, and then showed the parent widget. After that, I hid another parent widget, but the actual display sometimes showed 27 out of 30 images simultaneously, with the remaining three images appearing one by one. However, there were times when all 30 images would display together. I initially thought it was due to the time needed for painting high-resolution images in my paint event, so I used a for loop to simulate this time-consuming process. It takes about 10ms to paint each image. In the demo, even with a 1s delay, it does not result in displaying the images one by one; instead, all images are shown simultaneously after the paint event for each image completes.

                What I primarily want to know is whether there are any factors that could affect the order of display. I have been unable to identify the issue in my actual project.

                M Offline
                M Offline
                mpergand
                wrote on last edited by
                #10

                @Quiccz
                Try repaint() right after show()

                w1.show();
                w1.repaint();

                1 Reply Last reply
                0
                • Q Offline
                  Q Offline
                  Quiccz
                  wrote on last edited by
                  #11

                  My understanding of the event loop is that, after executing a.exec() in the main function, the program enters the event loop. Other threads can emit messages (such as when a QTimer's time is up), which will place the corresponding functions into the event loop. The event loop acts like a queue, where events are retrieved from the front of the queue and their corresponding functions are executed until each function is completed before moving to the next event.

                  If that's the case, why do we see w1.showall, w1.show, followed by pic show event, then parent show event, and finally w2.hideall and w2.hide? It appears that the show event doesn't enter the event loop but is instead a regular function call because it is invoked before w2.hide within my QTimer function.

                  In this scenario, the reason pic show event comes first is that after calling w1.showall, it realizes that the parent widget (w1) is not yet shown, so it doesn't trigger the show event. After w1 is shown, it doesn't immediately trigger w1's show event. Instead, it needs to iterate through the child widgets and invoke their show event if they are in the shown state.

                  1 Reply Last reply
                  0
                  • Q Offline
                    Q Offline
                    Quiccz
                    wrote on last edited by
                    #12

                    If i let w1 show first and add delay in paintevent and paint 11 pics and add repaint https://streamable.com/r8r0u9
                    6ba53d28-34ea-4ae1-ad9e-b74105523474-image.png
                    8ce4fcea-b465-41db-90ea-04cba83e3f97-image.png
                    6d6c9ba9-9a62-4822-b164-e07b3639d6ee-image.png

                    if i let w1.showall first https://streamable.com/izhzvq
                    198930f8-1f04-4815-a3df-534fec49443e-image.png

                    Pl45m4P 1 Reply Last reply
                    0
                    • Q Quiccz

                      If i let w1 show first and add delay in paintevent and paint 11 pics and add repaint https://streamable.com/r8r0u9
                      6ba53d28-34ea-4ae1-ad9e-b74105523474-image.png
                      8ce4fcea-b465-41db-90ea-04cba83e3f97-image.png
                      6d6c9ba9-9a62-4822-b164-e07b3639d6ee-image.png

                      if i let w1.showall first https://streamable.com/izhzvq
                      198930f8-1f04-4815-a3df-534fec49443e-image.png

                      Pl45m4P Offline
                      Pl45m4P Offline
                      Pl45m4
                      wrote on last edited by
                      #13

                      @Quiccz

                      The reason for this is the parent-child struture.
                      If you show the Parent first and then showAll childs (pics) in a loop, it works as in the first video.

                      If you call showAll first, all pics/childs are queued to be shown, but cant show up because their parent is hidden. When you then show the ParentWidget the queue is emptied and all childs show up without delay.

                      That would be my explanation for this. Could also have other influences


                      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                      ~E. W. Dijkstra

                      Q 1 Reply Last reply
                      0
                      • Pl45m4P Pl45m4

                        @Quiccz

                        The reason for this is the parent-child struture.
                        If you show the Parent first and then showAll childs (pics) in a loop, it works as in the first video.

                        If you call showAll first, all pics/childs are queued to be shown, but cant show up because their parent is hidden. When you then show the ParentWidget the queue is emptied and all childs show up without delay.

                        That would be my explanation for this. Could also have other influences

                        Q Offline
                        Q Offline
                        Quiccz
                        wrote on last edited by
                        #14

                        @Pl45m4 If I don't use repaint(), the display effect of case 1 will become like video 2. However, the logs indicate that the paintEvent of the picture has already finished, so why isn't it immediately displayed?

                        1 Reply Last reply
                        0
                        • Q Quiccz has marked this topic as solved on
                        • Q Offline
                          Q Offline
                          Quiccz
                          wrote on last edited by
                          #15

                          I found my program bug. so close it

                          1 Reply Last reply
                          0
                          • S Offline
                            S Offline
                            SimonSchroeder
                            wrote on last edited by
                            #16

                            There is no reason to call show() or hide() on your pictures. Just show and hide the parent widgets.

                            Here is my try to explain why with the order show() -> showAll() the pictures can appear one after the other. You are correct that the basic understanding of signals and slots is that events are queued inside the event loop. However, the default connection is an AutoConnection. If both sender and receiver are inside the same thread this defaults to a DirectConnection. This means that the event loop is skipped. This is especially true for repaint() which will immediately draw the widget. Because you are doing this in a loop (and PicWidget::paintEvent() has a delay) one picture must appear after the other. The general advice is to never use repaint(), but use update() instead. This can significantly increase performance. update() will gather several calls first if they appear quickly after another and only then call repaint(). I am not entirely sure about the underlying mechanism of update() or if the event loop is involved. show() itself will call update() (or something similar) internally. This means that several calls to show() also are first gathered.

                            With the order showAll() -> show() nothing will happen when calling show() for each picture because their parent widget is not visible. They are basically marked as visible and that's it. I don't think repaint() will do anything here as well. Only when show() is called on the parent will all the pictures be drawn. As this is a single paintEvent on the parent widget it will not be interrupted (drawing all of its children) before it can be shown on the screen (Qt does not paint on the screen directly, but uses double buffering, so that only after all draw commands of a single update() call are finished will they show on the screen). Just as I said in the beginning: Don't ever call show/hide on your PicWidgets. Just call it on the parent which will manage all the rest.

                            @Quiccz said in Question about show() hide():

                            I found my program bug. so close it

                            This is up to you. If you found a particular answer useful, click the three dots of that answer and mark the post as solved. Otherwise post your solution for others to find and select that one as the correct answer. (Somewhere there is also an option to mark it as solved without selecting an answer.)

                            Q 1 Reply Last reply
                            3
                            • S SimonSchroeder

                              There is no reason to call show() or hide() on your pictures. Just show and hide the parent widgets.

                              Here is my try to explain why with the order show() -> showAll() the pictures can appear one after the other. You are correct that the basic understanding of signals and slots is that events are queued inside the event loop. However, the default connection is an AutoConnection. If both sender and receiver are inside the same thread this defaults to a DirectConnection. This means that the event loop is skipped. This is especially true for repaint() which will immediately draw the widget. Because you are doing this in a loop (and PicWidget::paintEvent() has a delay) one picture must appear after the other. The general advice is to never use repaint(), but use update() instead. This can significantly increase performance. update() will gather several calls first if they appear quickly after another and only then call repaint(). I am not entirely sure about the underlying mechanism of update() or if the event loop is involved. show() itself will call update() (or something similar) internally. This means that several calls to show() also are first gathered.

                              With the order showAll() -> show() nothing will happen when calling show() for each picture because their parent widget is not visible. They are basically marked as visible and that's it. I don't think repaint() will do anything here as well. Only when show() is called on the parent will all the pictures be drawn. As this is a single paintEvent on the parent widget it will not be interrupted (drawing all of its children) before it can be shown on the screen (Qt does not paint on the screen directly, but uses double buffering, so that only after all draw commands of a single update() call are finished will they show on the screen). Just as I said in the beginning: Don't ever call show/hide on your PicWidgets. Just call it on the parent which will manage all the rest.

                              @Quiccz said in Question about show() hide():

                              I found my program bug. so close it

                              This is up to you. If you found a particular answer useful, click the three dots of that answer and mark the post as solved. Otherwise post your solution for others to find and select that one as the correct answer. (Somewhere there is also an option to mark it as solved without selecting an answer.)

                              Q Offline
                              Q Offline
                              Quiccz
                              wrote on last edited by
                              #17

                              @SimonSchroeder The reason I use show ()/hide() for pics is that in my actual project, each picture has a different display duration. For example, if there are three pictures in total, initially they are all displayed. After 1 second, the first picture is hidden. After 2 seconds, the second picture is hidden. After 3 seconds, the third picture is hidden, and then it switches to the next set of pictures.

                              1 Reply Last reply
                              0
                              • Q Quiccz has marked this topic as unsolved on
                              • Q Quiccz has marked this topic as solved on

                              • Login

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