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. Rendering error after changing the size of Window
Forum Updated to NodeBB v4.3 + New Features

Rendering error after changing the size of Window

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
windowimage
4 Posts 2 Posters 1.3k 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
    wangfys
    wrote on 18 Aug 2018, 16:34 last edited by
    #1

    I'm trying to implement a simple image viewer. I hope the image viewer can show the image without scaling, so I read the documentation about Image and find that I can use sourceSize property to get the real size. But there is something wrong after I change the size of Window to fit the size of the image.
    I use a FileDialog to choose a file and dynamiclly create a new Window to show the image.

    FileDialog {
            id: fileDialog
            title: "Choose a file"
            folder: shortcuts.home
            onAccepted: {
                var image = Qt.createComponent("qrc:/image.qml").createObject(appWindow, {});
                image.data[1].source = this.fileUrl;
            }
    }
    

    And this is my image.qml

    import QtQuick 2.11
    import QtQuick.Window 2.11
    import QtQuick.Controls 1.4
    Window {
        id: imageWindow
        visible: true
        width: 200
        height: 200
        ToolBar {
            height: 50
            Row {
                ToolButton {
                    width: 70
                    height: 45
                    text: qsTr("Exit")
                    onClicked: imageWindow.close()
                }
            }
        }
        Image {
            id: showImage
            y: 50
            onSourceSizeChanged: {
                imageWindow.height = this.sourceSize.height + 50;
                imageWindow.width = this.sourceSize.width;
            }
        }
    }
    

    I tried to change the Window's size when receiving sourceChanged signal, but failed because at that time, sourceSize is still (0, 0). So I choose to change the Window's size when receiving sourceSizeChanged signal.

    This image for test is 256*256:
    0_1534609620073_warp_test.png
    And I get a result like this:
    0_1534609719534_无标题.png

    There is an empty hole that looks like 200*200. After I drag the edge of the window it becomes normal immediately.
    0_1534609857041_无标题1.png

    So what's wrong with this process?

    D 1 Reply Last reply 18 Aug 2018, 17:18
    0
    • W wangfys
      18 Aug 2018, 16:34

      I'm trying to implement a simple image viewer. I hope the image viewer can show the image without scaling, so I read the documentation about Image and find that I can use sourceSize property to get the real size. But there is something wrong after I change the size of Window to fit the size of the image.
      I use a FileDialog to choose a file and dynamiclly create a new Window to show the image.

      FileDialog {
              id: fileDialog
              title: "Choose a file"
              folder: shortcuts.home
              onAccepted: {
                  var image = Qt.createComponent("qrc:/image.qml").createObject(appWindow, {});
                  image.data[1].source = this.fileUrl;
              }
      }
      

      And this is my image.qml

      import QtQuick 2.11
      import QtQuick.Window 2.11
      import QtQuick.Controls 1.4
      Window {
          id: imageWindow
          visible: true
          width: 200
          height: 200
          ToolBar {
              height: 50
              Row {
                  ToolButton {
                      width: 70
                      height: 45
                      text: qsTr("Exit")
                      onClicked: imageWindow.close()
                  }
              }
          }
          Image {
              id: showImage
              y: 50
              onSourceSizeChanged: {
                  imageWindow.height = this.sourceSize.height + 50;
                  imageWindow.width = this.sourceSize.width;
              }
          }
      }
      

      I tried to change the Window's size when receiving sourceChanged signal, but failed because at that time, sourceSize is still (0, 0). So I choose to change the Window's size when receiving sourceSizeChanged signal.

      This image for test is 256*256:
      0_1534609620073_warp_test.png
      And I get a result like this:
      0_1534609719534_无标题.png

      There is an empty hole that looks like 200*200. After I drag the edge of the window it becomes normal immediately.
      0_1534609857041_无标题1.png

      So what's wrong with this process?

      D Offline
      D Offline
      Diracsbracket
      wrote on 18 Aug 2018, 17:18 last edited by Diracsbracket
      #2

      @wangfys
      Really strange indeed. I tested your code, and it is perfectly working, for any images I use, including yours. I tested on Win10, Qt 5.11.0. Using onSourceChanged instead does indeed not work.

      Aside from not being very useful here, why not writing something like

      Window {
          id: imageWindow
          ...
          property alias showImage: showImage
          ...
          Image {
               id: showImage
               ...
          }
      

      and then use

      image.showImage.source = this.fileUrl;
      

      instead of

      image.data[1].source = this.fileUrl;
      
      1 Reply Last reply
      0
      • W Offline
        W Offline
        wangfys
        wrote on 19 Aug 2018, 09:20 last edited by wangfys
        #3

        @Diracsbracket Thanks for the suggestion!

        I find this problem only occurs when opening the first image.
        strange
        It's very confusing.

        And I try to avoid the problem by setting the Window invisible at first and then setting it visible after source is set.
        But I face another problem now. I add a feature for my program. I want to draw something. (In fact I'm doing a homework about image warping. I need to set some control points)

        Here is the effect:
        0_1534669584548_a.gif
        I draw some lines but nothing is showed.
        Then I pressed Exit button and keep pressed while exiting the button area so the button won't get a clicked signal and the Window won't close.

        Now everything works fine. Maybe there's something wrong that the program can't refresh or update rendering automatically at first.

        I implemented the drawing function according to the document about Scene Graph - Custom Geometry

        Here is my new version of image.qml

        import QtQuick 2.11
        import QtQuick.Window 2.11
        import QtQuick.Controls 1.4
        
        import CustomItem 1.0
        
        Window {
            id: imageWindow
            visible: false
            width: 200
            height: 200
            property alias showImage: showImage
            ToolBar {
                height: 50
                Row {
                    ToolButton {
                        width: 70
                        height: 45
                        text: qsTr("Exit")
                        onClicked: imageWindow.close()
                    }
                }
            }
            Image {
                id: showImage
                y: 50
                onSourceSizeChanged: {
                    imageWindow.height = this.sourceSize.height + 50;
                    imageWindow.width = this.sourceSize.width;
                    mouse.height = this.sourceSize.height;
                    mouse.width = this.sourceSize.width;
                    canvas.height = this.sourceSize.height;
                    canvas.width = this.sourceSize.width;
                }
            }
            MouseArea {
                id: mouse
                y: 50
                hoverEnabled: true
                property bool draw: false
                onPressed: {
                    draw = true;
                    points.addPoint(Qt.point(this.mouseX, this.mouseY));
                    points.addPoint(Qt.point(this.mouseX, this.mouseY));
                }
                onPositionChanged: {
                    if (draw === true)
                    {
                        points.setCurrentPoint(Qt.point(this.mouseX, this.mouseY));
                    }
                }
                onReleased: draw = false;
            }
            Rectangle {
                id: canvas
                y: 50
                color: "transparent"
                MyPointPairs {
                    id: points
                }
            }
        }
        

        I use qmlRegisterType<pointpairs>("CustomItem", 1, 0, "MyPointPairs"); in main.cpp to register pointpairs and here is my pointpairs.h

        #ifndef POINTPAIRS_H
        #define POINTPAIRS_H
        
        #include <QQuickItem>
        
        class pointpairs: public QQuickItem
        {
            Q_OBJECT
        public:
            pointpairs(QQuickItem *parent=nullptr);
            ~pointpairs();
        
            QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *);
        
        public slots:
            void addPoint(const QPointF &p);
            void setCurrentPoint(const QPointF &p);
        
        private:
            QVariantList points;
        };
        
        #endif // CLIENT_H
        

        and pointpairs.cpp

        #include "pointpairs.h"
        
        #include <QSGNode>
        #include <QSGFlatColorMaterial>
        
        pointpairs::pointpairs(QQuickItem *parent)
            : QQuickItem(parent)
        {
            setFlag(ItemHasContents, true);
        }
        
        pointpairs::~pointpairs()
        {
        }
        
        QSGNode *pointpairs::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
        {
            QSGGeometryNode *node = nullptr;
            QSGGeometry *geometry = nullptr;
        
            if (!oldNode)
            {
                node = new QSGGeometryNode;
                geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), points.count());
                geometry->setLineWidth(20);
                geometry->setDrawingMode(QSGGeometry::DrawLines);
                node->setGeometry(geometry);
                node->setFlag(QSGNode::OwnsGeometry);
                QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
                material->setColor(QColor(255, 165, 0));
                node->setMaterial(material);
                node->setFlag(QSGNode::OwnsMaterial);
            }
            else
            {
                node = static_cast<QSGGeometryNode *>(oldNode);
                geometry = node->geometry();
                geometry->allocate(points.count());
            }
            QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D();
            for (int i=0; i<points.count(); ++i)
            {
                vertices[i].set(points[i].toPointF().x(), points[i].toPointF().y());
            }
            node->markDirty(QSGNode::DirtyGeometry);
            return node;
        }
        
        void pointpairs::addPoint(const QPointF &p)
        {
            points << p;
            update();
        }
        
        void pointpairs::setCurrentPoint(const QPointF &p)
        {
            points[points.count() - 1] = p;
            update();
        }
        
        D 1 Reply Last reply 21 Aug 2018, 02:13
        0
        • W wangfys
          19 Aug 2018, 09:20

          @Diracsbracket Thanks for the suggestion!

          I find this problem only occurs when opening the first image.
          strange
          It's very confusing.

          And I try to avoid the problem by setting the Window invisible at first and then setting it visible after source is set.
          But I face another problem now. I add a feature for my program. I want to draw something. (In fact I'm doing a homework about image warping. I need to set some control points)

          Here is the effect:
          0_1534669584548_a.gif
          I draw some lines but nothing is showed.
          Then I pressed Exit button and keep pressed while exiting the button area so the button won't get a clicked signal and the Window won't close.

          Now everything works fine. Maybe there's something wrong that the program can't refresh or update rendering automatically at first.

          I implemented the drawing function according to the document about Scene Graph - Custom Geometry

          Here is my new version of image.qml

          import QtQuick 2.11
          import QtQuick.Window 2.11
          import QtQuick.Controls 1.4
          
          import CustomItem 1.0
          
          Window {
              id: imageWindow
              visible: false
              width: 200
              height: 200
              property alias showImage: showImage
              ToolBar {
                  height: 50
                  Row {
                      ToolButton {
                          width: 70
                          height: 45
                          text: qsTr("Exit")
                          onClicked: imageWindow.close()
                      }
                  }
              }
              Image {
                  id: showImage
                  y: 50
                  onSourceSizeChanged: {
                      imageWindow.height = this.sourceSize.height + 50;
                      imageWindow.width = this.sourceSize.width;
                      mouse.height = this.sourceSize.height;
                      mouse.width = this.sourceSize.width;
                      canvas.height = this.sourceSize.height;
                      canvas.width = this.sourceSize.width;
                  }
              }
              MouseArea {
                  id: mouse
                  y: 50
                  hoverEnabled: true
                  property bool draw: false
                  onPressed: {
                      draw = true;
                      points.addPoint(Qt.point(this.mouseX, this.mouseY));
                      points.addPoint(Qt.point(this.mouseX, this.mouseY));
                  }
                  onPositionChanged: {
                      if (draw === true)
                      {
                          points.setCurrentPoint(Qt.point(this.mouseX, this.mouseY));
                      }
                  }
                  onReleased: draw = false;
              }
              Rectangle {
                  id: canvas
                  y: 50
                  color: "transparent"
                  MyPointPairs {
                      id: points
                  }
              }
          }
          

          I use qmlRegisterType<pointpairs>("CustomItem", 1, 0, "MyPointPairs"); in main.cpp to register pointpairs and here is my pointpairs.h

          #ifndef POINTPAIRS_H
          #define POINTPAIRS_H
          
          #include <QQuickItem>
          
          class pointpairs: public QQuickItem
          {
              Q_OBJECT
          public:
              pointpairs(QQuickItem *parent=nullptr);
              ~pointpairs();
          
              QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *);
          
          public slots:
              void addPoint(const QPointF &p);
              void setCurrentPoint(const QPointF &p);
          
          private:
              QVariantList points;
          };
          
          #endif // CLIENT_H
          

          and pointpairs.cpp

          #include "pointpairs.h"
          
          #include <QSGNode>
          #include <QSGFlatColorMaterial>
          
          pointpairs::pointpairs(QQuickItem *parent)
              : QQuickItem(parent)
          {
              setFlag(ItemHasContents, true);
          }
          
          pointpairs::~pointpairs()
          {
          }
          
          QSGNode *pointpairs::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
          {
              QSGGeometryNode *node = nullptr;
              QSGGeometry *geometry = nullptr;
          
              if (!oldNode)
              {
                  node = new QSGGeometryNode;
                  geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), points.count());
                  geometry->setLineWidth(20);
                  geometry->setDrawingMode(QSGGeometry::DrawLines);
                  node->setGeometry(geometry);
                  node->setFlag(QSGNode::OwnsGeometry);
                  QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
                  material->setColor(QColor(255, 165, 0));
                  node->setMaterial(material);
                  node->setFlag(QSGNode::OwnsMaterial);
              }
              else
              {
                  node = static_cast<QSGGeometryNode *>(oldNode);
                  geometry = node->geometry();
                  geometry->allocate(points.count());
              }
              QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D();
              for (int i=0; i<points.count(); ++i)
              {
                  vertices[i].set(points[i].toPointF().x(), points[i].toPointF().y());
              }
              node->markDirty(QSGNode::DirtyGeometry);
              return node;
          }
          
          void pointpairs::addPoint(const QPointF &p)
          {
              points << p;
              update();
          }
          
          void pointpairs::setCurrentPoint(const QPointF &p)
          {
              points[points.count() - 1] = p;
              update();
          }
          
          D Offline
          D Offline
          Diracsbracket
          wrote on 21 Aug 2018, 02:13 last edited by Diracsbracket
          #4

          @wangfys
          I got exactly the same behavior as you. Although I never used the scene graph before, your example (+ the doc and the Custom Geometry example in Qt's examples) gave me a little crash course in the topic.
          http://doc.qt.io/qt-5/qtquick-visualcanvas-scenegraph.html

          Your example really should work as it seems you did everything as required by the doc. At my side, the lines become visible once I hover the mouse one the exit button. Possibly this is a bug?

          PS. Again, not being useful, I maybe I could suggest you to change the definition of your points from QVariantList points; to QVector<QPointF> points;

          Then you can use:

                  const float x = static_cast<float>(points[i].x());
                  const float y = static_cast<float>(points[i].y());
                  vertices[i].set(x, y);
          

          rather than

                vertices[i].set(points[i].toPointF().x(), points[i].toPointF().y());
          

          as it saves you a couple of calls to toPointF().

          1 Reply Last reply
          0

          2/4

          18 Aug 2018, 17:18

          • Login

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