c++ - 将图像从 c++ 更新到 QML
问题描述
我正在尝试将 QImage 从 c++ 更新为 QML,
我使用的方法来自:https ://www.huber.xyz/?p=477
我实现了 QQuickPaintedItem - 显示了初始 QImage,但是如果我在那里收到信号(FileWatcher),我找不到从 c++ 更新 QImage 的方法。
我的实现看起来像:
QML:
ImageItem {
id: liveImageItem
height: parent.height
width: parent.width
objectName: "liveImageItem"
}
我用以下方式注册图像:
qmlRegisterType<QUIQImageItem>("imageItem", 1, 0, "ImageItem");
图像的实现:
ImageItem::ImageItem(QQuickItem *parent) : QQuickPaintedItem(parent) {
qDebug() << Q_FUNC_INFO << "initializing new item, parent is: " << parent;
this->current_image = QImage(":/resources/images/logo.png");
}
void ImageItem::paint(QPainter *painter) {
qDebug() << Q_FUNC_INFO << "paint requested...";
QRectF bounding_rect = boundingRect();
QImage scaled = this->current_image.scaledToHeight(bounding_rect.height());
QPointF center = bounding_rect.center() - scaled.rect().center();
if (center.x() < 0)
center.setX(0);
if (center.y() < 0)
center.setY(0);
painter->drawImage(center, scaled);
}
QImage ImageItem::image() const {
qDebug() << Q_FUNC_INFO << "image requested...";
return this->current_image;
}
void ImageItem::setImage(const QImage &image) {
qDebug() << Q_FUNC_INFO << "setting new image...";
this->current_image = image;
emit imageChanged();
update();
}
如何在 c++ 端获取 ImageItem 的引用以通过 setImage 管理 Image 的更新?
这种方式可行还是我应该尝试其他解决方案?
我试图通过
QList<ImageItem*> res = engine->findChildren<ImageItem*>();
并且:
QList<ImageItem*> res = engine->findChildren<ImageItem*>("liveImageItem");
ImageItems (res) 列表始终为空。
解决方案
一般来说,您应该避免直接从 C++ 修改在 QML 中创建的项目,在此之前我将通过将图像添加为 qproperty 来改进您的实现:
*。H
#ifndef IMAGEITEM_H
#define IMAGEITEM_H
#include <QImage>
#include <QQuickPaintedItem>
class ImageItem : public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY(QImage image READ image WRITE setImage NOTIFY imageChanged)
public:
ImageItem(QQuickItem *parent = nullptr);
QImage image() const;
void setImage(const QImage &image);
void paint(QPainter *painter);
signals:
void imageChanged();
private:
QImage m_image;
};
#endif // IMAGEITEM_H
*.cpp
#include "imageitem.h"
#include <QDebug>
#include <QPainter>
ImageItem::ImageItem(QQuickItem *parent):QQuickPaintedItem(parent)
{
qDebug() << Q_FUNC_INFO << "initializing new item, parent is: " << parent;
setImage(QImage(":/resources/images/logo.png"));
}
QImage ImageItem::image() const
{
qDebug() << Q_FUNC_INFO << "image requested...";
return m_image;
}
void ImageItem::setImage(const QImage &image)
{
qDebug() << Q_FUNC_INFO << "setting new image...";
if(image == m_image)
return;
m_image = image;
emit imageChanged();
update();
}
void ImageItem::paint(QPainter *painter)
{
if(m_image.isNull())
return;
qDebug() << Q_FUNC_INFO << "paint requested...";
QRectF bounding_rect = boundingRect();
QImage scaled = m_image.scaledToHeight(bounding_rect.height());
QPointF center = bounding_rect.center() - scaled.rect().center();
if (center.x() < 0)
center.setX(0);
if (center.y() < 0)
center.setY(0);
painter->drawImage(center, scaled);
}
在这一部分中,我将回答您的直接问题,尽管这不是最好的,因为如果您不知道如何处理,您可能会遇到问题,例如,如果您在StackView
Page 中设置项目,因为每次更改时都会创建和删除它们页。
QObject *obj = engine.rootObjects().first()->findChild<QObject*>("liveImageItem");
if(obj){
QImage image = ...;
QQmlProperty::write(obj, "image", image);
}
示例: main.cpp
#include "imageitem.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlProperty>
#include <QTime>
#include <QTimer>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
qsrand(QTime::currentTime().msec());
qmlRegisterType<ImageItem>("com.eyllanesc.org", 1, 0, "ImageItem");
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
QObject *obj = engine.rootObjects().first()->findChild<QObject*>("liveImageItem");
QTimer timer;
if(obj){
QObject::connect(&timer, &QTimer::timeout, [obj](){
QImage image(100,100, QImage::Format_ARGB32);
image.fill(QColor(qrand()%255, qrand()%255, qrand()%255));
QQmlProperty::write(obj, "image", image);
});
timer.start(1000);
}
return app.exec();
}
对我来说,一个更好的主意是实现一个 Helper 并在 QML 中建立连接:
#include "imageitem.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlProperty>
#include <QQmlContext>
#include <QTime>
#include <QTimer>
class Helper: public QObject{
Q_OBJECT
Q_PROPERTY(QImage image READ image WRITE setImage NOTIFY imageChanged)
public:
QImage image() const{ return m_image; }
void setImage(const QImage &image){
if(m_image == image)
return;
m_image = image;
emit imageChanged();
}
signals:
void imageChanged();
private:
QImage m_image;
};
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
qsrand(QTime::currentTime().msec());
qmlRegisterType<ImageItem>("com.eyllanesc.org", 1, 0, "ImageItem");
QGuiApplication app(argc, argv);
Helper helper;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("helper", &helper);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
QTimer timer;
QObject::connect(&timer, &QTimer::timeout, [&helper](){
QImage image(100,100, QImage::Format_ARGB32);
image.fill(QColor(qrand()%255, qrand()%255, qrand()%255));
helper.setImage(image);
});
timer.start(1000);
return app.exec();
}
#include "main.moc"
*.qml
...
ImageItem{
id: liveImageItem
height: parent.height
width: parent.width
}
Connections{
target: helper
onImageChanged: liveImageItem.image = helper.image
}
...
推荐阅读
- android - 我的应用程序在模拟器中运行良好,但在真实设备中运行时崩溃
- java - int 值在函数中不返回?
- html - 相对链接导致没有 SSL?
- apache-kafka - Kafka Streams:GlobalStore 线程安全吗?
- android - Cordova 的 Ionic 3 构建失败:cordova\node_modules\cordova-common\src\superspawn.js:169:23
- mysql - 向其他用户授予执行功能权限
- jsp - 登录后如何将sessionAttribute获取到用户配置文件
- python - 从列表中拉出标题并创建一个带有并排标题的 DataFrame 以列出元素
- debugging - 如何识别内存中的汇编“调用”指令?
- javascript - XMLHttpRequest 响应空