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. Overlaying QWidgets
QtWS25 Last Chance

Overlaying QWidgets

Scheduled Pinned Locked Moved Unsolved General and Desktop
11 Posts 2 Posters 13.4k 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.
  • W Offline
    W Offline
    webzoid
    wrote on 14 Oct 2017, 08:34 last edited by
    #1

    I probably already know the answer to this but, is there any way of overlaying one QWidget on top of another QWidget without the bottom widget being the top widgets parent?

    1 Reply Last reply
    0
    • C Offline
      C Offline
      Chris Kawa
      Lifetime Qt Champion
      wrote on 14 Oct 2017, 09:03 last edited by Chris Kawa
      #2

      They could be siblings or further relatives but they do need to have a common ancestor to be placed in the same window.
      You have control over the stacking order of such widgets with raise(), lower() and stackUnder().

      The other option is that they don't have a common ancestor i.e. they become separate windows, but then it becomes a little trickier to handle the various moves, resizes and stacking order.

      1 Reply Last reply
      1
      • W Offline
        W Offline
        webzoid
        wrote on 14 Oct 2017, 09:30 last edited by
        #3

        @Chris-Kawa thanks for your reply. There is a common parent for both QWidgets and, ideally, I'd be using a QGridLayout so that both of the QWidgets fill the entire layout (one underneath each other). I'm pretty sure this won't be possible though.

        1 Reply Last reply
        0
        • C Offline
          C Offline
          Chris Kawa
          Lifetime Qt Champion
          wrote on 14 Oct 2017, 09:42 last edited by
          #4

          No, two widgets in the same layout can't overlay each other. It's the actual job of the layout that they don't. One of them (usually the top one) needs to be "free floating" i.e. not in a layout. Resizing needs to be done manually.

          1 Reply Last reply
          1
          • W Offline
            W Offline
            webzoid
            wrote on 14 Oct 2017, 09:52 last edited by
            #5

            Would a QStackedLayout help me in this instance? Literally just discovered such a wonder.

            The QWidget to be hidden is a QQuickWidget and I need to ensure that, even when not visible, the QML is still rendered correctly.

            1 Reply Last reply
            0
            • C Offline
              C Offline
              Chris Kawa
              Lifetime Qt Champion
              wrote on 14 Oct 2017, 09:57 last edited by
              #6

              That depends on what you want. In a stacked layout only one widget is visible at a time. The others are not drawn. Stack layout is useful to implement something like QTabWidget.

              What are you trying to do exactly?

              1 Reply Last reply
              0
              • W Offline
                W Offline
                webzoid
                wrote on 14 Oct 2017, 10:16 last edited by
                #7

                I'll give you a cut-down version of what I'm wanting to achieve...

                I've posted on this forum previously about my target application and I'm still trying to figure out a nice solution. So basically, I have a 3rd party COM object which draws a "nautical chart" using a Windows GDI DC. I'm also trying to integrate the QML Map into this application for added flexibility for the end user.

                The only way I've managed to figure out how to get both the QML and COM/DC to play nicely so far is to put a QWidget on top of a QQuickWidget and to allow the child to fill the QQuickWidget entirely. The problem with doing this is that firstly, I need to use the winId of the top-most QWidget in order to draw the COM object but with doing this, I then get thousands of QML warnings which I am unable to stop - however, I can grab the rendered QML and draw it as a QImage onto my QWidget as a layer beneath the COM object (I really hope this makes sense so far).

                Ultimately, this isn't really a nice solution and the QML warnings make further debugging of the application impossible. I have tried other solutions - custom QQuickItem which would draw the 3rd party COM object but this doesn't work. As soon as I go anywhere near a winId, this breaks the QML stuff.

                My thinking thus far is that if I am able to stack the QQuickWidget and the QWidget but without setting the any parents then I won't get any of the annoying QML warnings and I'll also be able to quickly swap between the two views.

                If there is the possibility of off-screen rendering both the QML and the COM then bringing them both together in another single QWidget, that'd be perfect but my tinkering so far hasn't come up with a workable solution for this.

                Sorry for the waffle...

                1 Reply Last reply
                0
                • C Offline
                  C Offline
                  Chris Kawa
                  Lifetime Qt Champion
                  wrote on 14 Oct 2017, 13:13 last edited by Chris Kawa
                  #8

                  Maybe instead of trying to marry QML with GDI you could draw with GDI to a bitmap and then paint that in a regular widget's paint event. For example something like this:

                  class GDIWrapper : public QWidget
                  {
                  public:
                      void paintEvent(QPaintEvent*) override
                      {
                          HDC hDC = CreateCompatibleDC(NULL);
                          DWORD* pSrcData = nullptr;
                          BITMAPINFO bmi = { sizeof( BITMAPINFOHEADER ), width(), height(), 1, 32, BI_RGB, 0, 0, 0, 0, 0};
                          HBITMAP bitmap = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (void**)&pSrcData, 0, 0);
                          HGDIOBJ prev_bitmap = SelectObject(hDC, bitmap);
                  
                          DrawSomething(hDC); //this would be the 3rd party draw
                  
                          SelectObject(hDC, prev_bitmap);
                          GdiFlush();
                  
                          { //scoped so that QImage does not outlive bitmap
                              QImage img ((uchar*)pSrcData, width(), height(), QImage::Format_RGB32);
                              QPainter p(this);
                              p.drawImage(0,0,img);
                          }
                  
                          DeleteObject(bitmap);
                          DeleteDC(hDC);
                      }
                  };
                  

                  Of course you'd need to add the necessary error checking.
                  You could then easily overlay that over QQuickWidget without the need for native handle (winId):

                  auto gdi_wrapper = new GDIWrapper();
                  auto quick_widget = new QQuickWidget(QUrl::fromLocalFile(":/some.qml"));
                  quick_widget->setLayout(new QVBoxLayout);
                  quick_widget->layout()->addWidget(gdi_wrapper);
                  
                  W 1 Reply Last reply 14 Oct 2017, 15:58
                  3
                  • C Chris Kawa
                    14 Oct 2017, 13:13

                    Maybe instead of trying to marry QML with GDI you could draw with GDI to a bitmap and then paint that in a regular widget's paint event. For example something like this:

                    class GDIWrapper : public QWidget
                    {
                    public:
                        void paintEvent(QPaintEvent*) override
                        {
                            HDC hDC = CreateCompatibleDC(NULL);
                            DWORD* pSrcData = nullptr;
                            BITMAPINFO bmi = { sizeof( BITMAPINFOHEADER ), width(), height(), 1, 32, BI_RGB, 0, 0, 0, 0, 0};
                            HBITMAP bitmap = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (void**)&pSrcData, 0, 0);
                            HGDIOBJ prev_bitmap = SelectObject(hDC, bitmap);
                    
                            DrawSomething(hDC); //this would be the 3rd party draw
                    
                            SelectObject(hDC, prev_bitmap);
                            GdiFlush();
                    
                            { //scoped so that QImage does not outlive bitmap
                                QImage img ((uchar*)pSrcData, width(), height(), QImage::Format_RGB32);
                                QPainter p(this);
                                p.drawImage(0,0,img);
                            }
                    
                            DeleteObject(bitmap);
                            DeleteDC(hDC);
                        }
                    };
                    

                    Of course you'd need to add the necessary error checking.
                    You could then easily overlay that over QQuickWidget without the need for native handle (winId):

                    auto gdi_wrapper = new GDIWrapper();
                    auto quick_widget = new QQuickWidget(QUrl::fromLocalFile(":/some.qml"));
                    quick_widget->setLayout(new QVBoxLayout);
                    quick_widget->layout()->addWidget(gdi_wrapper);
                    
                    W Offline
                    W Offline
                    webzoid
                    wrote on 14 Oct 2017, 15:58 last edited by
                    #9

                    @Chris-Kawa Thanks for your suggestion. Looks like a very good one to me - will try this later.

                    The ultimate solution, I guess, would be using your code in a custom 'QQuickItem' so that I could add it to the QML - then I could make use of additional QML features.

                    Or maybe I'm trying to push the QML integration too far. I dunno.

                    1 Reply Last reply
                    0
                    • W Offline
                      W Offline
                      webzoid
                      wrote on 17 Oct 2017, 09:22 last edited by
                      #10

                      @Chris-Kawa I've just implemented your suggestion and the resulting QImage appears to be rotated and flipped. Bizarre!

                      1 Reply Last reply
                      0
                      • C Offline
                        C Offline
                        Chris Kawa
                        Lifetime Qt Champion
                        wrote on 17 Oct 2017, 19:54 last edited by
                        #11

                        Coordinate systems and related data storage often differ between frameworks. If you can't control how the 3rd party organizes its output just set the right flip/rotation using setTransform() on your painter before drawing.

                        1 Reply Last reply
                        2

                        10/11

                        17 Oct 2017, 09:22

                        • Login

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