首页 文章

Qml中的QScrollArea:Flickable QQuickPaintedItem

提问于
浏览
2

我试图在Qml的帮助下实现与 QScrollArea (在小部件世界中)类似的东西 . 我决定探测基于 Flickable 加上 QQuickPaintedItem 的项目(在我的例子中名为Drawer):

Flickable {
  ...
  onContentXChanged(): {
  drawer.update()
  }

Drawer {
  id: drawer
  ...
}

抽屉的渲染目标设置为 FrameBufferObject . 它的绘画功能如下所示:

void Drawer::paint(QPainter *painter)
{
   // Some function to compute rect which is needed to be redrawn
   QRect updateRect = computeUpdateRect();

   // How to shift contents of Frame buffer, e.g. to right, and draw only updateRect in this space?
}

想象一下我们如何在 QScrollArea 小部件中滚动,例如向左:视口的所有条目都向右移动,左边唯一的小矩形被重绘 . 我想用 Flickable QQuickPaintedItem 做同样的事情 . 但我无法理解一些事情:

如何操作 QQuickPaintedItem 中的Frame Buffer对象?也许有更正确的方法在QML中实现 QScrollArea

顺便说一下, QQuickPaintedItem 默认启用双缓冲?

用于实现 Flickable :提供有关任务的更多信息:我有一个非常大的"picture" . 所以我无法将它整个加载到内存中,但我必须使用像viewport这样的东西来浏览它 .

1 回答

  • 2

    当您想要在较小的区域中封装较大的内容并在其中导航时,可以使用滚动区域或可滑动的区域 . 在你的情况下......不是这样的 . 您实际上并没有使用滚动区域,因为您的图像永远不会大于滚动区域大小,您只想伪造它,这实际上非常简单:

    #include <QQuickPaintedItem>
    #include <QImage>
    #include <QPainter>
    
    class PImage : public QQuickPaintedItem {
        Q_OBJECT
    public:
        PImage(QQuickItem * p = 0) : QQuickPaintedItem(p), xpos(0), ypos(0) {}
        void paint(QPainter *painter) {
            if (!source.isNull()) painter->drawImage(QRect(0, 0, width(), height()), source, QRect(xpos, ypos, width(), height()));
            else painter->fillRect(QRect(0, 0, width(), height()), Qt::black);
        }
    public slots:
        bool load(QString path) {
            source = QImage(path);
            return !source.isNull();
        }
        void moveBy(int x, int y) {
            int ox, oy;
            // don't go outside the image
            ox = x + xpos + width() <= source.width() ? x + xpos : source.width() - width();
            oy = y + ypos + height() <= source.height() ? y + ypos : source.height() - height();
            if (ox < 0) ox = 0;
            if (oy < 0) oy = 0;
            if (ox != xpos || oy != ypos) {
                xpos = ox;
                ypos = oy;
                update();
            }
        }
    private:
        QImage source;
        int xpos, ypos;
    };
    

    在QML方面:

    PImage {
        width: 300
        height: 300
        Component.onCompleted: load("d:/img.jpg") // a big image
        MouseArea {
            property int ix
            property int iy
            anchors.fill: parent
            onPressed: {
                ix = mouseX
                iy = mouseY
            }
            onPositionChanged: {
                parent.moveBy(ix - mouseX, iy - mouseY)
                ix = mouseX
                iy = mouseY
            }
        }
    }
    

    这只是一个快速的基本示例,有很多空间可以进行润色和改进 . 另请注意,如果源rect的大小与目标rect不同,则可以轻松实现放大或缩小 . 您可以将其挂钩到一个可以轻弹以获得“动态滚动”而不是鼠标区域 .

相关问题