Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. [SOLVED] How to draw a transparent hole inside a QQuickView / QQuickWindow based on a custom QQuickItem?
Forum Updated to NodeBB v4.3 + New Features

[SOLVED] How to draw a transparent hole inside a QQuickView / QQuickWindow based on a custom QQuickItem?

Scheduled Pinned Locked Moved QML and Qt Quick
10 Posts 2 Posters 11.6k Views 1 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.
  • B Offline
    B Offline
    billouparis
    wrote on last edited by
    #1

    Hello,
    I have the following problem, I do not manage to create a transparent hole inside a QQuickView, through a customed QQuitItem.

    Here is what I have:

    • a C++ custom QQuickItem, CustomQQuickItem, which is registered in qml so I can access it from a QML file
    • a C++ main application, creating a QQuickView.
    • a main QML file as follows:

    @import QtQuick 2.0
    import LWQQuickItem 1.0

    Rectangle {
    id:idScreenUIZ0_0
    width: 800
    height: 480
    color: "blue"

    CustomQQuickItem {
        id: idCustomQuickItem
        x: 100
        y: 100
        width: 500
        height: 100
    }
    

    }@

    I would like my CustomQQuickItem instance to 'draw' transparency in the QQuickView with the given position and size (100,100,500,100).

    So I overrode the QSGNode * updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) method of the QQuickItem to do this transparent hole.

    @QSGNode * LWQQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
    {

    //    retrieve window in which the QQuickItem is drawn
    // Returns the window in which this item is rendered.
    QQuickWindow *pQQuickWindow;
    pQQuickWindow = QQuickItem::window();
    
    if (pQQuickWindow != NULL)
    {
        // Here I would like to draw a transparent area in the window itself
        pQQuickWindow->setColor(QColor(0,0,0,0));
        ;
    }
    else
    {
        qDebug()<<"qquickwindow not found!";
    }
    
    //Not sure what I should return here
    return oldNode;
    

    }
    @

    Anyone has any idea if this is possible at all? basically, is it possible to:

    • either draw directly in the underlying window a transparent area ?
    • or define a specific scene graph node that will draw a transparent area in the rendering window?

    Thank you for providing me any hint to help me achieve this.
    Regards,
    Bill

    1 Reply Last reply
    0
    • M Offline
      M Offline
      mlong
      wrote on last edited by
      #2

      I don't think you're going to be able to take the approach you're presenting. An item on top of another item can't "erase" it's parent. If the overlayed item is transparent, it's just going to show its parent behind it.

      If you want a rectangular "hole" in a solid background, you could always fake it using a container item and four solid panels to fill in around your transparent area...

      @
      Item {
      id:idScreenUIZ0_0
      width: 800
      height: 480

      Rectangle {  // The "Hole"
          id: hole
          color: "transparent"
      
          x: 100
          y: 100
          width: 500
          height: 100
      }
      
      Rectangle {
          id: leftpanel
          color: "blue"
          anchors.left: parent.left
          anchors.top: parent.top
          anchors.bottom: parent.bottom
          anchors.right: hole.left
      }
      Rectangle {
          id: rightpanel
          color: "blue"
          anchors.left: hole.right
          anchors.right:parent.right
          anchors.top: parent.top
          anchors.bottom: parent.bottom
      }
      Rectangle {
          id: toppanel
          color: "blue"
          anchors.top: parent.top
          anchors.bottom: hole.top
          anchors.left: leftpanel.right
          anchors.right: rightpanel.left
      }
      Rectangle {
          id: bottompanel
          color: "blue"
          anchors.top: hole.bottom
          anchors.bottom: hole.bottom
          anchors.left: leftpanel.right
          anchors.right: rightpanel.left
      }
      

      }
      @
      Brain to terminal, ymmv

      Software Engineer
      My views and opinions do not necessarily reflect those of anyone -- living or dead, real or fictional -- in this universe or any other similar multiverse node. Void where prohibited. Your mileage may vary. Caveat emptor.

      1 Reply Last reply
      0
      • B Offline
        B Offline
        billouparis
        wrote on last edited by
        #3

        Thank you,
        But I really need to draw a transparent area inside a QQuickView that may first render opaque elements under my hole and then even other opaque elements on top of my hole. I see my requirement as some kind of mask, that could be also overlapped by other opaque elements, depending on the rendering sequence. I hope my need is clearly expressed here.

        I am sure this must be possible, and I agree to say that my approach is not right to achieve this, that's why I am looking for the right approach!
        Unfortunately I am not very familiar with this SG stuff, and really need to get some competence in this domain :=)

        Thank you for your proposal, but sadly it won't satisfy my use case.
        Regards,
        Bill

        1 Reply Last reply
        0
        • M Offline
          M Offline
          mlong
          wrote on last edited by
          #4

          You can use the same kind of thing as above, but utilize different Z properties for your items. By setting the Z depth you can draw things stacked however you want them rather than having to rely on the order that they're drawn.

          Software Engineer
          My views and opinions do not necessarily reflect those of anyone -- living or dead, real or fictional -- in this universe or any other similar multiverse node. Void where prohibited. Your mileage may vary. Caveat emptor.

          1 Reply Last reply
          0
          • B Offline
            B Offline
            billouparis
            wrote on last edited by
            #5

            I must not have been clear enough in my explanations, and I am sorry about it.
            Let's imagine I have a full screen background image, and now i want to draw a transparent hole in this background image (to begin with, and any shape maybe later), of any dimension, at any location, at any moment, want to be able to actually activate or deactivate this hole at run time. And on top of that, I would lile to be able to draw other smaller opaque elements over the transparent created hole, event elements that could partially cover the transparent region and bit of the background image still visible.

            Is this explanation clearer now?
            Regards,
            Bill

            1 Reply Last reply
            0
            • M Offline
              M Offline
              mlong
              wrote on last edited by
              #6

              So, if you have a background image and you cut a hole in it arbitrarily, what is to be shown behind it?

              Perhaps I'm still not understanding, but again, though, one item cannot "paint transparency" onto another item to erase part of the separate item.

              Software Engineer
              My views and opinions do not necessarily reflect those of anyone -- living or dead, real or fictional -- in this universe or any other similar multiverse node. Void where prohibited. Your mileage may vary. Caveat emptor.

              1 Reply Last reply
              0
              • B Offline
                B Offline
                billouparis
                wrote on last edited by
                #7

                I would like to see any other application window displayed underneath my Qt application.
                But I don't think that the QQuickItem is a good approach, because I am not sure I can define a SGNode able to modify parent nodes to change basically their alpha values. Or maybe it is possible?

                Maybe I shall try with the Qt Graphical Effects, or a simple shader, but still not sure if my shader could apply to my background image though...

                I am gonna make a visual illustration of what I would like to achieve so you can get the whole picture.
                Regards,
                Bill

                1 Reply Last reply
                0
                • B Offline
                  B Offline
                  billouparis
                  wrote on last edited by
                  #8

                  Here you go, is the use case clear now?
                  !http://i46.tinypic.com/10fb0g3.png()!

                  1 Reply Last reply
                  0
                  • B Offline
                    B Offline
                    billouparis
                    wrote on last edited by
                    #9

                    Finally achieved my goal BUT WITHOUT CUSTOM QQUICKITEM, I rather used a QGraphicalEffect / Mask

                    main.cpp
                    @int main(int argc, char *argv[])
                    {
                    QGuiApplication app(argc, argv);

                    QtQuick2ApplicationViewer viewer;
                    viewer.setSurfaceType(QSurface::OpenGLSurface);
                    
                    QSurfaceFormat format;
                    format.setAlphaBufferSize(8);
                    format.setRenderableType(QSurfaceFormat::OpenGL);
                    qDebug() <&lt; format.hasAlpha();
                    viewer.setFormat(format);
                    
                    QColor color;
                    color.setRedF(0.0);
                    color.setGreenF(0.0);
                    color.setBlueF(0.0);
                    color.setAlphaF(0.0);
                    viewer.setColor(color);
                    
                    viewer.setClearBeforeRendering(true);
                    
                    //viewer.setFlags(Qt::FramelessWindowHint);
                    
                    viewer.setMainQmlFile&#40;QStringLiteral("qml/MaskTest/main.qml"&#41;);
                    viewer.showExpanded();
                    
                    return app.exec();
                    

                    }
                    @

                    main.qml
                    @
                    import QtQuick 2.0
                    import QtGraphicalEffects 1.0
                    import "."

                    Item {
                    id: idRoot
                    width: 800
                    height: 480

                    Image {
                        id: idBackGround
                        x: 0
                        y: 0
                        width: 800
                        height: 480
                        source: "../../resource/background.jpg"
                        visible: false
                    }
                    
                    RectangularMask {
                        id: idRectangularMask
                        transpX: idSliderX.value
                        transpY: idSliderY.value
                        transpWidth: idSliderW.value
                        transpHeight: idSliderH.value
                        visible: false
                    }
                    
                     OpacityMask {
                        anchors.fill: idRoot
                        source: idBackGround
                        maskSource: idRectangularMask
                    
                    }
                    
                    Image {
                        id: idTop
                        x: 200
                        y: 200
                        source: "../../resource/top.png"
                    }
                    
                    Slider {
                        id: idSliderX
                        x:100
                        y: 440
                        width: 200
                        minimum: 0
                        maximum: 800
                    }
                    Slider {
                        id: idSliderY
                        x:100
                        y: 460
                        width: 200
                        minimum: 0
                        maximum: 480
                    }
                    Slider {
                        id: idSliderW
                        x:350
                        y: 440
                        width: 200
                        minimum: 0
                        maximum: 800
                    }
                    Slider {
                        id: idSliderH
                        x:350
                        y: 460
                        width: 200
                        minimum: 0
                        maximum: 480
                    }
                    

                    }
                    @

                    RectangularMask.qml
                    @import QtQuick 2.0

                    Item {
                    property int transpX: 0
                    property int transpY: 0
                    property int transpWidth: 0
                    property int transpHeight: 0

                    width: 800
                    height: 480
                    
                    Rectangle {
                        color: "transparent"
                        Rectangle{
                            x:0
                            y:0
                            width: 800
                            height: transpY
                            color: "black"
                        }
                    
                        Rectangle{
                            x:0
                            y:transpY+transpHeight
                            width: 800
                            height: 480-y
                            color: "black"
                        }
                    
                        Rectangle{
                            x:0
                            y:0
                            width: transpX
                            height: 480
                            color: "black"
                        }
                    
                        Rectangle{
                            x:transpX+transpWidth
                            y:0
                            width: 800 - x
                            height: 480
                            color: "black"
                        }
                    }
                    

                    }
                    @

                    Slider.qml
                    @import QtQuick 2.0

                    Item {
                    id: slider; width: 400; height: 16

                    // value is read/write.
                    property real value: 1
                    onValueChanged: updatePos();
                    property real maximum: 1
                    property real minimum: 1
                    property int xMax: width - handle.width - 4
                    onXMaxChanged: updatePos();
                    onMinimumChanged: updatePos();
                    
                    function updatePos() {
                        if (maximum &gt; minimum) {
                            var pos = 2 + (value - minimum) * slider.xMax / (maximum - minimum);
                            pos = Math.min(pos, width - handle.width - 2);
                            pos = Math.max(pos, 2);
                            handle.x = pos;
                        } else {
                            handle.x = 2;
                        }
                    }
                    
                    Rectangle {
                        anchors.fill: parent
                        border.color: "white"; border.width: 0; radius: 8
                        gradient: Gradient {
                            GradientStop { position: 0.0; color: "#66343434" }
                            GradientStop { position: 1.0; color: "#66000000" }
                        }
                    }
                    
                    Rectangle {
                        id: handle; smooth: true
                        y: 2; width: 30; height: slider.height-4; radius: 6
                        gradient: Gradient {
                            GradientStop { position: 0.0; color: "lightgray" }
                            GradientStop { position: 1.0; color: "gray" }
                        }
                    
                        MouseArea {
                            id: mouse
                            anchors.fill: parent; drag.target: parent
                            drag.axis: Drag.XAxis; drag.minimumX: 2; drag.maximumX: slider.xMax+2
                            onPositionChanged: { value = (maximum - minimum) * (handle.x-2) / slider.xMax + minimum;
                            }
                        }
                    }
                    

                    }
                    @

                    1 Reply Last reply
                    1
                    • B Offline
                      B Offline
                      billouparis
                      wrote on last edited by
                      #10

                      I still have an issue related now to the Mask / QGraphicalEffect itself... Will look for it later...
                      The effect is working, here the result:
                      http://www.youtube.com/watch?v=aPPu--7IzuY

                      Regards,
                      Bill

                      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