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. The invisible QApplication
Forum Updated to NodeBB v4.3 + New Features

The invisible QApplication

Scheduled Pinned Locked Moved Unsolved General and Desktop
15 Posts 4 Posters 4.9k Views 2 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 rturrentine

    We support a command line option for hiding the GUI of our Qt based app. This works on Windows, Linux and Solaris.

    Hiding a window can't be done in the constructor so you need to use a single shot timer.

    In the main window constructor,

            qApp->setQuitOnLastWindowClosed( false );
            QTimer::singleShot( 0, this, SLOT( hide() ) );
    

    The main app creates the window but does not call show or anything on it. We simply call the exec method for our application object.

    Moose2342M Offline
    Moose2342M Offline
    Moose2342
    wrote on last edited by
    #4

    @rturrentine Thanks a lot for your response. I just gave that a test. In my scenario the window remains hidden but the widgets are nor receiving paint events either.
    I suppose this is due to the nature of Qt's event loop. In my research everything I read pointed towards "Your widgets will not be painted as long as they are hidden.". But I do need them painted so I can intercept the events and render() into my own buffer.
    Or is there another way? Maybe I can send those events myself in a QTimer triggered frequency? Is that a viable approach?

    Cheers,
    Moose

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

      Hi
      If a Widget is hidden it gets no paint events as far as i know.

      One thing you could test is the render() function
      http://doc.qt.io/qt-5.5/qwidget.html#render

      It lets you draw a widget directly to pixmap so I think it can work with hidden
      widget but never tested it.

      QPixmap pixmap(mywidget->size());
      mywidget->render(&pixmap);

      I know u already use render() but I wonder if u tried calling it directly, not using paintevent at all?

      One thing that could also be issue is that while hidden , it do not receive resize events
      so might be of wrong size even if Render() does work.

      Maybe you already tested all this. Just asking :)

      Moose2342M 1 Reply Last reply
      0
      • E Offline
        E Offline
        eureka
        wrote on last edited by
        #6

        @Moose2342 said:

        I want a show() that doesn't show.

        I'm quite new to Qt. Please explain why setting the widget geometry (X, Y) to negative values doesn't take the widget off screen .. effectively hiding the widget?

        mrjjM 1 Reply Last reply
        0
        • E eureka

          @Moose2342 said:

          I want a show() that doesn't show.

          I'm quite new to Qt. Please explain why setting the widget geometry (X, Y) to negative values doesn't take the widget off screen .. effectively hiding the widget?

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

          @eureka
          Hi
          For some platforms that might work.
          But some platforms/windows managers do not allow it or
          it can have side effects in multiple monitor setup.
          Some windows managers might even help you and move it into view :)

          1 Reply Last reply
          0
          • mrjjM mrjj

            Hi
            If a Widget is hidden it gets no paint events as far as i know.

            One thing you could test is the render() function
            http://doc.qt.io/qt-5.5/qwidget.html#render

            It lets you draw a widget directly to pixmap so I think it can work with hidden
            widget but never tested it.

            QPixmap pixmap(mywidget->size());
            mywidget->render(&pixmap);

            I know u already use render() but I wonder if u tried calling it directly, not using paintevent at all?

            One thing that could also be issue is that while hidden , it do not receive resize events
            so might be of wrong size even if Render() does work.

            Maybe you already tested all this. Just asking :)

            Moose2342M Offline
            Moose2342M Offline
            Moose2342
            wrote on last edited by
            #8

            @mrjj Yes, I tried calling this directly. It only produces an empty buffer though. I suppose this is due to the widget in question being quite complex.
            It is a QWebEngineWidget.
            It creates a lot of underlying child widgets and they pass their sizes and status back and forth. It wasn't even straight forward hooking up to it's paint event at all.

            So when I trigger render on it, say from a QTimer without having the widget visible it simply paints a white screen into the buffer. At this point I can only assume that the size information are not correctly passed to the child widgets if it is invisible.

            So far all my tests with manually generating events were inconclusive or negative. Personally I believe messing with the event loop too much will only bring complexity and no solution. My gut tells me a solution will work best if I can redirect the graphical output to the now legendary /dev/null without Qt knowing about it.

            Thank you very much for the hint though!

            Moose

            mrjjM 1 Reply Last reply
            0
            • Moose2342M Moose2342

              @mrjj Yes, I tried calling this directly. It only produces an empty buffer though. I suppose this is due to the widget in question being quite complex.
              It is a QWebEngineWidget.
              It creates a lot of underlying child widgets and they pass their sizes and status back and forth. It wasn't even straight forward hooking up to it's paint event at all.

              So when I trigger render on it, say from a QTimer without having the widget visible it simply paints a white screen into the buffer. At this point I can only assume that the size information are not correctly passed to the child widgets if it is invisible.

              So far all my tests with manually generating events were inconclusive or negative. Personally I believe messing with the event loop too much will only bring complexity and no solution. My gut tells me a solution will work best if I can redirect the graphical output to the now legendary /dev/null without Qt knowing about it.

              Thank you very much for the hint though!

              Moose

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

              @Moose2342

              Well Qt will queue resize events if widget is hidden. ( as far as i know)
              so if your widget does stuff in these events then it will not have happened.

              I was wondering if u played around with
              http://doc.qt.io/qt-5.5/qcoreapplication.html#postEvent

              In theory , you could construct the same events and send to it.

              But yes, it suddenly becomes complex and I agree with your gut feeling that a
              simple solution exists once found :)

              Moose2342M 1 Reply Last reply
              0
              • mrjjM mrjj

                @Moose2342

                Well Qt will queue resize events if widget is hidden. ( as far as i know)
                so if your widget does stuff in these events then it will not have happened.

                I was wondering if u played around with
                http://doc.qt.io/qt-5.5/qcoreapplication.html#postEvent

                In theory , you could construct the same events and send to it.

                But yes, it suddenly becomes complex and I agree with your gut feeling that a
                simple solution exists once found :)

                Moose2342M Offline
                Moose2342M Offline
                Moose2342
                wrote on last edited by
                #10

                @mrjj
                I have tested the resize events. Contrary to what I thought hide() or any other means of hiding it don't cause any such events. At least not that I see them.
                About the postEvent, that does sound interesting. I will need those things anyway, once I start creating user interaction on the by then hopefully invisible widget.

                But to hide it in the first place (or making it work without show()ing it) I wouldn't know which events to send.
                What I tried before was QShowEvent. After creating the widget and before I go into QApplication::exec() I tried sending one, hoping to fool the widget. It didn't work though.
                The widget never went into paint(). And when I sent the paint myself it crashed somewhere in QtOpenGLs innards. Apparently some initial contexts have not been created. I guess show() is necessary for it to work.

                I'm currently trying to move the widget into its own process to live remotely on its own machine where I'm not bothered by the output. I was so hoping to avoid the network bridge for such a seemingly simple thing...

                Cheers,
                Moose

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

                  Oh
                  So later the users will also click on the texture of the widgets
                  and it needs to react as the real widget would?
                  That is pretty advanced. :)

                  what types of widget do u need to support ? i if may ask.

                  Moose2342M 1 Reply Last reply
                  0
                  • mrjjM mrjj

                    Oh
                    So later the users will also click on the texture of the widgets
                    and it needs to react as the real widget would?
                    That is pretty advanced. :)

                    what types of widget do u need to support ? i if may ask.

                    Moose2342M Offline
                    Moose2342M Offline
                    Moose2342
                    wrote on last edited by Moose2342
                    #12

                    @mrjj
                    Well, that's the plan. :-)
                    At the moment I will be OK with basic interaction such as mouse wheel and perhaps clicks. No keyboard or other stuff yet.

                    In the long run I am hoping to adapt more widgets as long as they are content with my basic means of interaction.
                    For now, QWebEngine is primary target as it gives me a modern web browser in-a-box with all capabilities I need. My research ha turned up no other implementation but Qt's here that can do this. Also, due to its complexity and overall weirdness (OpenGL, child widgets) I suppose if it works with that chances are it works with everything.

                    At the moment I am also looking into Windows 10's new virtual desktops. If I can open an application on one of those I wouldn't have to bridge the network and could grab the buffer via IPC or shared memory or something. This desktop would be my /dev/null. As long as Qt doesn't notice it's not actually visible that is.

                    Cheers,
                    Moose

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

                      @Moose2342 said:
                      Thats a fine plan :)
                      To boldly go .. ;)

                      Yes, if you can get QWebEngine to work as hidden then most other
                      widgets will just work / you will have the code to do it.

                      Oh, virtual desktops is a pretty good idea if not considered hidden by Qt when other desktop is active.
                      Far more fun than running on a other pc and need to handle that traffic too.

                      Moose2342M 1 Reply Last reply
                      0
                      • mrjjM mrjj

                        @Moose2342 said:
                        Thats a fine plan :)
                        To boldly go .. ;)

                        Yes, if you can get QWebEngine to work as hidden then most other
                        widgets will just work / you will have the code to do it.

                        Oh, virtual desktops is a pretty good idea if not considered hidden by Qt when other desktop is active.
                        Far more fun than running on a other pc and need to handle that traffic too.

                        Moose2342M Offline
                        Moose2342M Offline
                        Moose2342
                        wrote on last edited by
                        #14

                        @mrjj
                        Thanks! To boldly go indeed. As a final little update in the matter I would like to add that my approach with the Windows 10 virtual desktops seems to work. I have created a shared memory server which runs the QApplication and renders into a shared memory buffer. This buffer is now consumed where the app-in-a-box used to live. And to my great relief Qt, being oblivious to new Windows features, seems not to notice that the application is actually invisible, so events are processed fine. Let's just pray this stays that way.

                        As a welcome side effect my actual application now suffers a lot less performance impact from creating and running the Qt app since it has only to access the buffer. Next step are the user events.

                        Thanks for your input!

                        Cheers,
                        Moose

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

                          Ok. super :)
                          Thank you for the feedback. it's good to know that being on other desktop is not the
                          same as being hidden.

                          Good luck with user interaction :)

                          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