我不明白如何使用QQuickPaintedItem
类(或者其他方法?)在QML中显示图像。
我的程序当前正在使用QImage
和一个ImageProvider显示它,它可以正常工作但随机崩溃,所以我想尝试另一种方法。
此外,每次传输新帧时都应刷新图像。
我从uchar
原始数据中获取信息,但我不知道如何从原始数据中绘制。
此外,新的原始数据大约为60 fps,因此QML需要以此速率刷新图像。
编辑:
代码的其他部分:
我的课程是:
class StreamPainter : public QQuickPaintedItem
{
Q_OBJECT
public:
StreamPainter(QQuickItem *p = 0):QQuickPaintedItem(p){}
~StreamPainter();
void paint(QPainter *painter){painter->drawImage(QPoint(0, 0), _streamImage);}
public slots:
void onImageAvailable(QImage image) {
_streamImage = image;
update();
private:
QImage _streamImage;
};
主要:
对于无效的属性名称,这是由于导入StreamPainter 1.0,似乎它不喜欢这个名称,因为它被灌输了,我已经将它改为myModule并且错误消失了。
qmlRegisterType<StreamPainter>("myModule", 1, 0, "StreamPainter");
创建对象和线程:
streamImage = new StreamPainter();
myPipeThread = new PipeThread(streamImage);
线程构造函数:
PipeThread::PipeThread(StreamPainter* spvideostr)
:QThread(),
_namedPipe(INVALID_HANDLE_VALUE),
_spvideostr(spvideostr),
_abort(false),
_rawData(NULL)
{
...
}
线程类,我已添加:
signals:
void imageAvailable(QImage image);
然后在我的线程中,我进行连接,并在此期间创建QImage并发出信号:
connect(this, SIGNAL(imageAvailable(QImage)), _spvideostr, SLOT(onImageAvailable(QImage)));
while(...)
QImage clImage(_rawData, IMG_WIDTH, IMG_HEIGHT, QImage::Format_Indexed8);
emit imageAvailable(clImage);
QML:
import QtQuick 2.0
import MyModule 1.0
StreamPainter {
width : 100
height : 100
答案 0 :(得分:0)
这很简单,你要做的就是用paint()
方法绘制图像:
void paint(QPainter *painter) {
painter->drawImage(QPoint(0, 0), yourImage);
}
每次update()
更改时都会致电yourImage
。
不要绘制原始数据,用适当的格式从中创建QImage
并绘制它。您可以使用静态方法QImage fromData(const uchar *data, int size, const char *format = Q_NULLPTR)
。由于QImage
是隐式共享对象,因此每次获得新数据时都可以有效yourImage = QImage::fromData(...)
,然后update()
。
编辑:
您应该在QML中创建对象。另外,看看如何使用线程,请记住UI元素只能从主线程访问。这意味着您无法执行此操作:
_spvideostr->setStreamImage(clImage);
_spvideostr->update();
当您从另一个线程访问UI对象时。相反,您应该使用带有排队连接的信号和插槽,通过该连接传递图像,然后设置图像并从update()
的插槽中调用StreamPainter
。
你不需要:
Q_PROPERTY(QImage streamImage READ streamImage WRITE setStreamImage NOTIFY streamImageChanged)
此图片只能从该课程中访问。所以你不需要那些:
QImage streamImage();
void setStreamImage(QImage clImage);
signals:
void streamImageChanged(QImage Image);
你需要的是:
public slots:
void onImageAvaiable(QImage image) { ...set image and call update }
在PipeThread
中,您需要一个信号void imageAvaiable(QImage)
,将imageAvaiable
连接到onImageAvaiable
并发出图片:
QImage clImage(_rawData, IMG_WIDTH, IMG_HEIGHT, QImage::Format_Indexed8);
emit imageAvaiable(clImage);
答案 1 :(得分:0)
在我的例子中,我使用组件内部的函数刷新QML中的图像,如下所示:
Image {
id: imageLogo
cache: false
anchors.fill: parent
//anchors.leftMargin: 20
Layout.preferredWidth: Math.round(parent.width / 1.5)
Layout.preferredHeight: Math.round(parent.height * 2)
function reloadImage() {
var oldSource = source
source = ""
source = oldSource
}//function to refresh the source
}
然后我只在你想重新加载图像的地方调用这个函数
imageLogo.reloadImage()