使用更新功能扩展 QML 图像类型
Posted
技术标签:
【中文标题】使用更新功能扩展 QML 图像类型【英文标题】:Extend QML Image type with an update function 【发布时间】:2016-12-15 10:40:43 【问题描述】:正如大多数熟悉 QML 的人所知,QML Image
中没有内置的“刷新”功能。
我想创建一个新的 QML 类型,比如 RefreshableImage
来缓解这个问题,而不需要改变源代码,我觉得这是一个丑陋的 hack,因为它会渗透到模型-视图关系的所有层,而且切换行为是不自然的。此外,在Image
上设置不同的source
会破坏任何可能已设置的绑定(这实际上是问题的核心:我想要一个可更新的图像来保持其绑定,并且与 QML 隔离)。我知道我需要调用一些信号来实际刷新图像,这很好。
我很难找到有关扩展 Qt 自己的 Image
的文档,以便我可以强制它重新加载其源代码。我想避免编写一个完整的组件,该组件大多严重复制 Image
以添加一个功能。有没有办法像我想的那样扩展内置组件?
小笔记:
由于外部情况,我仅限于 Qt 5.5。 我们使用source
作为QQuickImageProvider
用来获取实际QImage
的底层图像对象的UUID。因此,我不想在更新图像时更改它。
【问题讨论】:
为什么你需要用相同的source
等更新Image
?这不是同一张图吗?
@folibis 技术上是的,但基础数据已经改变。我们使用 QML ImageProviders 从我们的数据结构中将 Qimage 提供给 QML。我们使用的 id 是我们系统中图像的 uuid,因此我们可以从该 uuid 检索其他地方的实际对象。为了简单起见,我们只是重用了这个 uuid。
嗯,好的,您应该在问题中指定这一点。我想这很重要。
也许你应该使用 UUID/version 而不仅仅是 UUID?我认为这是合乎逻辑的,因为 image => imageid 是一对一的链接。如果相同的 ID 涉及不同的图像/图像数据,那就不好了。顺便说一句,图像数据如何变化?
好吧。它与相同的(概念)图像有关,只是图像数据发生了变化。如果我可以为它编写一个组件,我真的很想避免添加版本绒毛......
【参考方案1】:
您可以创建一个 RefreshableImage
类型来隐藏丑陋的源代码。
有一种简单的方法是为源引入一个新属性:
import QtQuick 2.0
Image
id: root
property string refreshableSource
source: refreshableSource
function refresh()
source = "";
source = Qt.binding(function() return refreshableSource );
你必须这样使用它:RefreshableImage refreshableSource: "image.jpg"
。
如果您仍想使用source
作为属性,您可以使用一些别名恶作剧来实现。由于只有在组件完全初始化后才会激活别名,因此您可以覆盖 Image
的 source
属性,但仍然可以访问底层。
import QtQuick 2.0
Image
id: root
property alias actualUnderlyingSource: root.source //this refers to Image.source and not the newly created source alias
property alias source: root.refreshableSource
property string refreshableSource
actualUnderlyingSource: refreshableSource
function refresh()
actualUnderlyingSource = "";
actualUnderlyingSource = Qt.binding(function() return refreshableSource );
然后你可以像 RefreshableImage source: "image.jpg"
这样使用它,这实际上会修改 refreshableSource
属性
【讨论】:
有没有办法可以添加一些底层 C++ 来将其连接到实际的图像对象?如中,我可以用 C++ 扩展 QML 图像吗?我猜ImageRefresher
C++/QML 组件/对象的组合会使这成为可能?我希望它能够收听/观察附加到相关 uuid 的对象。谢谢!【参考方案2】:
从带有自定义项的模型中直接使用 QImage 的粗略骨架
class DirectImage : public QQuickPaintedItem
Q_OBJECT
Q_PROPERTY(QImage image READ image WRITE setImage NOTIFY imageChanged)
public:
void paint(QPainter *painer);
void setImage(const QImage &image);
;
void DirectImage::paint(QPainter *painter)
painter->drawImage(m_image.scaled(width(), height()):
void DirectImage::setImage(const QImage &image)
m_image = image;
emit imageChanged();
setImplicitWidth(image.width());
setImplicitHeight(image.height());
update();
注册方式
qmlRegisterType<DirectImage>("MyElements", 1, 0, "RefreshableImage");
使用途径
import MyElements 1.0
// ...
RefreshableImage
image: model.image
当被要求提供图像角色时,模型只返回QImage
,每当图像发生变化时,就会发出带有图像角色的dataChanged()
信号。
如果需要按需生成图片,模型可以先返回空图片或者占位图片,当实际内容可用时发出dataChanged()
信号。
【讨论】:
以上是关于使用更新功能扩展 QML 图像类型的主要内容,如果未能解决你的问题,请参考以下文章