Qml中的QScrollArea:Flickable + QQuickPaintedItem [英] QScrollArea in Qml: Flickable + QQuickPaintedItem

查看:357
本文介绍了Qml中的QScrollArea:Flickable + QQuickPaintedItem的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Qml的帮助下实现与QScrollArea类似的东西(在小部件世界中). 我决定探究Flickable加基于QQuickPaintedItem的项目(在我的情况下命名为Drawer):

I'm trying to realize something similiar to QScrollArea (in widgets world) with the help of Qml. I decided to probe Flickable plus QQuickPaintedItem based item (named Drawer in my case):

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

Drawer {
  id: drawer
  ...
}

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

Drawer's render target is set to FrameBufferObject. Its paint function looks like this:

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做同样的事情.但是我有些不明白:

Imagine how we do scrolling in QScrollArea widget, e.g. to left: all entry of viewport is shifted to right and the only small rect in left is redrawn. I want to do the same with Flickable+QQuickPaintedItem. But I can't understand some things:

如何在QQuickPaintedItem内部操纵帧缓冲区对象? 也许有一些更正确的方法可以在QML中实现QScrollArea?

How can I manipulate Frame Buffer object inside QQuickPaintedItem? Maybe there is some more right way to implement QScrollArea in QML?

顺便问一下,QQuickPaintedItem默认情况下是否启用了双缓冲?

By the way, is double buffering enabled by default in QQuickPaintedItem?

对于使用Flickable实施: 提供有关任务的更多信息:我有一个很大的图片".因此,我无法将其全部加载到内存中,但必须使用诸如视口之类的东西在其中进行导航.

For implementing with Flickable: To provide more info about task: I have a very big "picture". So I cannot load it whole into memory, but I have to navigate through it with something like viewport.

推荐答案

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

A scroll area or a flickable are used when you want to encapsulate a larger content in a smaller area and navigate around it. And in your case that is... not the case. You are not practically using a scroll area as your image is never larger than the scroll area size, you just want to fake it, which is actually quite easy:

#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
        }
    }
}

这只是一个简单的基本示例,还有很多改进和改进的空间.还要注意,如果源矩形的大小与目标矩形的大小不同,则可以轻松实现放大或缩小.您可以将其挂在轻弹上,以获取动态滚动"而不是鼠标区域.

This is just a quick basic example, there is a lot of room to polish and improve. Also note that if the source rect is different size than the target rect, you can easily achieve zooming in or out. You can hook it to a flickable to get the "kinetic scrolling" instead of the mouse area.

这篇关于Qml中的QScrollArea:Flickable + QQuickPaintedItem的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆