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. Is it possible to force update everything for a QWidget without actually show it on the screen ?
QtWS25 Last Chance

Is it possible to force update everything for a QWidget without actually show it on the screen ?

Scheduled Pinned Locked Moved Solved General and Desktop
9 Posts 3 Posters 1.7k 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.
  • S Offline
    S Offline
    stronger1234
    wrote on last edited by
    #1

    As the topic said, is there a way to perform all updates for a toplevel QWidget, including it's geometry, backing store, and transient parent window, ... , but without actually show it on the screen? (e.g. do everything that QWidget::show() does, without calling the Windows API ShowWindow() )? I've tried Qt::WA_DontShowOnScreen but it seems to miss something to do, like updateTransientParent.

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      Can you explain what result you would like to achieve ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • S Offline
        S Offline
        stronger1234
        wrote on last edited by
        #3

        I need to integrate a QAxWidget as a floating tool panel into my main UI framework, and I make a custom tool panel window frame for the axWidget, then I call axWidget's setParent(windowFrame, Qt::FramelessWindowHint | Qt::Tool) and write some code to keep it's geometry within the windowFrame (for some reason I have to make the axWidget a toplevel window). The axWidget's parent may change from a windowFrame to a new one, and the original windowFrame may be destroyed before the axWidget is shown to the new one. As a result, after axWidget's parent change, if the original windowFrame is destroyed before axWidget is shown, a call to axWidget's show() will never take effect. It seems that the record of transcientParent of axWidget's platform window is not updated while calling axWidget's setParent. I take axWidget only as an example but the problem may exist on any toplevel window.

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Maybe @hskoglund may have an idea about that matter. I haven't use QAxWidget at all yet.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          1
          • S Offline
            S Offline
            stronger1234
            wrote on last edited by stronger1234
            #5

            It doesn't matter about the QAxWidget. The problem looks happen on any top level window that has a transient parent. Consider this segment of code:

            	QApplication app(argc, argv);
            	auto widgetA = new QWidget, widgetB = new QWidget;
            	widgetA->setWindowTitle("widgetA");
            	widgetB->setWindowTitle("widgetB");
            	widgetA->show();
            	widgetB->show();
            	auto pushButton = new QPushButton("pushButton");
            	pushButton->setParent(widgetA, Qt::Tool);
            	pushButton->show();
            	QObject::connect(pushButton, &QPushButton::clicked, [=]()
            	{
            		pushButton->setParent(widgetB, Qt::Tool);
            		delete widgetA;
            		pushButton->show();
            	});
            	return app.exec();
            

            When the pushButton is clicked, I change pushButton's parent to widgetB and then delete widgetA, the pushButton is supposed not to be destroyed and show normally as a tool window, right? But it doesn't. Is it a QT-BUG or am I missing something?

            1 Reply Last reply
            0
            • hskoglundH Offline
              hskoglundH Offline
              hskoglund
              wrote on last edited by
              #6

              Hi, using delete on the widget is a bit too abrupt for Qt, better is to use deleteLater, it will accomplish the transfer of ownership in an orderly manner, so something like this:

              ...
              QObject::connect(pushButton, &QPushButton::clicked, [=]()
              {
                  pushButton->setParent(widgetB, Qt::Tool);
                  widgetA->deleteLater();
                  pushButton->show();
              });
              
              1 Reply Last reply
              1
              • S Offline
                S Offline
                stronger1234
                wrote on last edited by stronger1234
                #7

                It's ok to call deleteLater() for the example above, but what if the pushButton also needs to show later by receiving some other signals? For example:

                QObject::connect(pushButton, &QPushButton::clicked, [=]()
                {
                    pushButton->setParent(widgetB, Qt::Tool);
                    widgetA->deleteLater();
                    QTimer::singleShot(1000, [=]() { pushButton->show(); });
                });
                

                The pushButton still fail to show. I think maybe it's a better idea to immediately update the transient parent of a toplevel window during the call of its setParent(), instead of update it in the next call of show().

                1 Reply Last reply
                0
                • hskoglundH Offline
                  hskoglundH Offline
                  hskoglund
                  wrote on last edited by
                  #8

                  Yeah, you need to "anchor" the pushButton to the new QWidget before deleting the old parent QWidget, I usually do a show()/hide() to keep the pushButton happy, e.g. in your case:

                  QObject::connect(pushButton, &QPushButton::clicked, [=]()
                  {
                      pushButton->setParent(widgetB, Qt::Tool);
                      widgetA->deleteLater();
                      pushButton->show(); pushButton->hide();
                      QTimer::singleShot(1000, [=]() { pushButton->show(); });
                  });
                  

                  (Those show()/calls() will not be visible for the user, only needed for keeping the pushButton alive.)

                  1 Reply Last reply
                  1
                  • S Offline
                    S Offline
                    stronger1234
                    wrote on last edited by stronger1234
                    #9

                    Hmm... it may be a workaround for my case. However, the show() and hide() operations are not totally invisible for the user. When I debug the code and step over the first pushButton->show(), taking a break before the pushButton->hide(), I still see a not painted tool window showing there. I guess there might be a very short flash while running on some low performace machines. I'm wondering whether there is something better like ensureReparented(), which is similar to ensurePolished() for getting geometry, font, palette, ... before the widget is shown.
                    Anyway, your workaround is acceptable for me at present. 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