[英]Qml Image doesn't refresh on source change and signal reception
I created "fruit_swap" project in Qt Creator bt choosing-- Application -> Qt Quick Application -> Qt 5.5.我在 Qt Creator 中创建了“fruit_swap”项目 bt 选择--应用程序-> Qt 快速应用程序-> Qt 5.5。 In fruit_swap, 'main()' function calls forkSwapper() which forks a process that swaps fruit image (apple <--> pear) once every second.
在fruit_swap 中,'main()' 函数调用forkSwapper(),它分叉一个进程,每秒交换一次水果图像(apple <--> pear)。
The swapping is done inside setImageURL() method which also emits "imageURLChanged" signal for the qml.交换是在 setImageURL() 方法中完成的,该方法还为 qml 发出“imageURLChanged”信号。 From the output(shown below at the bottom), the signal is proven to be delivered to the qml side.
从输出(如下图底部),信号被证明被传递到 qml 端。
I was expecting the qml Image swapping.我期待 qml 图像交换。 However, it didn't.
然而,它没有。 The first image shown('pear') stayed motionlessly.
显示的第一个图像(“梨”)一动不动。 What could have I done wrong?
我可能做错了什么? Any suggestion is welcome.
欢迎任何建议。 I uploading every single source code below.
我上传了下面的每一个源代码。
/* generated by Qt Creator */ /* 由 Qt Creator 生成 */
TEMPLATE = app
QT += qml quick
CONFIG += c++11
SOURCES += main.cpp \
imageitem.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Default rules for deployment.
include(deployment.pri)
HEADERS += \
imageitem.h
DISTFILES += \
FruitFrame.qml
/* https://quickgit.kde.org/?p=scratch%2Fsune%2Fimageitem.git */ /* https://quickgit.kde.org/?p=scratch%2Fsune%2Fimageitem.git */
#include <QQuickPaintedItem>
/**
* @brief QQuickItem to show images/pixmaps/colors in a QML item
*
* As opposed to the Image from plain qml, this works on
* QImages, QPixmaps and QColors
*/
class ImageItem : public QQuickPaintedItem
{
// Q_PROPERTY(QVariant imageData READ imageData() WRITE setImageData
// NOTIFY imageDataChanged)
Q_OBJECT
Q_PROPERTY(QVariant imageURL READ imageURL() WRITE setImageURL
NOTIFY imageURLChanged)
public:
explicit ImageItem(QQuickItem *parent = 0);
/**
* \reimpl
*/
Q_INVOKABLE void paint(QPainter* painter) Q_DECL_OVERRIDE;
/**
* @brief image data u-ed by this item
* @return a QVariant wrapping the data
*/
QVariant imageData() const;
/**
* @brief Sets the image data
* @param newData
*/
void setImageData(const QVariant& newData);
QVariant imageURL() const;
/**
* @brief Sets the image data
* @param newData
*/
void setImageURL(const QVariant& fileName);
Q_SIGNALS:
/**
* @brief imageChanged
*/
void imageDataChanged();
void imageURLChanged();
private:
enum Type {
Unknown,
Pixmap,
Image,
Color
};
Type m_type;
QVariant m_imageData;
QVariant m_imageURL;
QRectF scaledRect(const QRect& sourceRect) const;
};
#endif // IMAGEITEM_H
/* https://quickgit.kde.org/?p=scratch%2Fsune%2Fimageitem.git */ /* https://quickgit.kde.org/?p=scratch%2Fsune%2Fimageitem.git */
#include "imageitem.h"
#include <QPainter>
#include <qobjectdefs.h>
ImageItem::ImageItem(QQuickItem *parent) :
QQuickPaintedItem(parent)
{
m_imageURL = QUrl::fromLocalFile(QString("apple.jpg"));
}
void ImageItem::paint(QPainter* painter)
{
switch(m_type) {
case Unknown: {
return;
}
case Image: {
QImage image = m_imageData.value<QImage>();
painter->drawImage(scaledRect(image.rect()), image);
return;
}
case Pixmap: {
QPixmap pixmap = m_imageData.value<QPixmap>();
painter->drawPixmap(scaledRect(pixmap.rect()).toRect(), pixmap);
return;
}
case Color: {
QColor color = m_imageData.value<QColor>();
painter->fillRect(contentsBoundingRect(),color);
return;
}
}
}
QVariant ImageItem::imageData() const
{
return m_imageData;
}
QVariant ImageItem::imageURL() const
{
return m_imageURL;
}
void ImageItem::setImageURL(const QVariant &fileName)
{
m_imageURL = QUrl::fromLocalFile(fileName.value<QString>());
if (m_imageURL.canConvert<QUrl>()) {
QUrl url = m_imageURL.value<QUrl>();
if (!url.isEmpty() && url.isValid()
&& url.isLocalFile())
{
qDebug() << "URL is valid";
} else {
qDebug() << "URL is INvalid";
}
} else {
qDebug() << "URL is INvalid";
}
emit imageURLChanged();
}
void ImageItem::setImageData(const QVariant& newData)
{
switch(newData.userType()) {
case QMetaType::QPixmap: {
m_type = Pixmap;
break;
}
case QMetaType::QImage: {
m_type = Image;
break;
}
case QMetaType::QColor: {
m_type = Color;
break;
}
default: {
m_type = Unknown;
break;
}
}
m_imageData = newData;
emit imageDataChanged();
}
QRectF ImageItem::scaledRect(const QRect& sourceRect) const
{
QRectF targetRect = contentsBoundingRect();
QSizeF scaledSize;
double widthScale = targetRect.width() / sourceRect.width();
double heightScale = targetRect.height() / sourceRect.height();
if(widthScale < heightScale) {
scaledSize.setHeight(sourceRect.height() * widthScale);
scaledSize.setWidth(sourceRect.width() *widthScale);
} else {
scaledSize.setHeight(sourceRect.height() * heightScale);
scaledSize.setWidth(sourceRect.width() *heightScale);
}
QRectF result = QRectF(targetRect.left() + targetRect.width() /2 - scaledSize.width() /2,
targetRect.top() + targetRect.height()/2 - scaledSize.height()/2,
scaledSize.width(),scaledSize.height());
// QRectF result(QPointF(0,0),scaledSize);
qDebug() << result << targetRect << sourceRect << widthScale << heightScale ;
return result;
}
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QImage>
#include <unistd.h>
#include "imageitem.h"
void forkSwapper(ImageItem * fImage);
int main(int argc, char *argv[])
{
qmlRegisterType<ImageItem>("ImageItem",1,0,"ImageItem");
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
ImageItem *fImage = new ImageItem();
fImage->setImageURL("fruit.jpg");
engine.rootContext()->setContextProperty("cpp_imageURL", fImage);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
forkSwapper(fImage);
return app.exec();
}
void forkSwapper(ImageItem * fImage) {
int pid = fork();
if (pid == 0) {
int i = 0;
while (true) {
if (i++ % 2 == 0)
fImage->setImageURL("apple.jpg");
//std::system("cp apple.jpg fruit.jpg");
else
fImage->setImageURL("pear.jpg");
//std::system("cp pear.jpg fruit.jpg");
qDebug() << "fruit image changed";
sleep(1);
}
_exit (EXIT_FAILURE);
} else {
qDebug() << "swapper forked, PID:" << pid;
}
}
import QtQuick 2.5
import ImageItem 1.0
Rectangle {
property alias mouseArea: mouseArea
width: 360
height: 360
MouseArea {
id: mouseArea
anchors.fill: parent
Connections {
target: cpp_imageURL
onImageURLChanged: {
fruit_image.update();
// fruit_image.source = cpp_imageURL.imageURL;
console.log("image UURL-" + cpp_imageURL.imageURL);
}
}
Image {
id: fruit_image
x: 39
y: 94
width: 274
height: 204
source: cpp_imageURL.imageURL
cache: false
}
}
Text {
anchors.centerIn: parent
text: "Hello World"
anchors.verticalCenterOffset: -137
anchors.horizontalCenterOffset: -104
}
}
import QtQuick 2.5
import QtQuick.Window 2.2
import ImageItem 1.0
Window {
visible: true
width: 360
height: 460
FruitFrame {
anchors.fill: parent
mouseArea.onClicked: {
Qt.quit();
}
}
}
Starting /home/jbpark03/wem/fruit_swap/build/fruit_swap...
QML debugging is enabled. Only use this in a safe environment.
URL is valid
URL is valid
qml: image UURL-file:apple.jpg
fruit image changed
swapper forked, PID: 3078
URL is valid
qml: image UURL-file:pear.jpg
fruit image changed
URL is valid
qml: image UURL-file:apple.jpg
fruit image changed
URL is valid
qml: image UURL-file:pear.jpg
fruit image changed
URL is valid
qml: image UURL-file:apple.jpg
END.结尾。
The code works perfectly well.该代码运行良好。 I think the problem is you're blocking the Qt application because you're using
sleep
.我认为问题在于您正在阻止 Qt 应用程序,因为您正在使用
sleep
。
In fact, you see the image pear.jpg
because is the first image shown after fruit.jpg
and before any sleep
.事实上,您会看到
pear.jpg
图像,因为它是在fruit.jpg
之后和任何sleep
之前显示的第一张图像。
If, for example, you use a QTimer
or a QThread
, you will check the image is properly updated.例如,如果您使用
QTimer
或QThread
,您将检查图像是否正确更新。
Example:例子:
mytimer.h mytimer.h
#ifndef MYTIMER_H
#define MYTIMER_H
#include <QObject>
#include <QTimer>
#include "imageitem.h"
class MyTimer : public QObject
{
Q_OBJECT
public:
explicit MyTimer(ImageItem * fImage, QObject *parent = 0);
private:
QTimer *timer;
ImageItem *myImage;
signals:
public slots:
void update();
};
#endif // MYTIMER_H
mytimer.cpp mytimer.cpp
#include <QDebug>
#include <QTest>
#include "mytimer.h"
MyTimer::MyTimer(ImageItem * fImage, QObject *parent) : QObject(parent)
{
myImage = fImage;
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1000);
}
void MyTimer::update()
{
myImage->setImageURL(":pear.jpg");
QTest::qWait(250);
myImage->setImageURL(":apple.jpg");
}
With this timer, we're going to change the image every 1 second.使用这个计时器,我们将每 1 秒更改一次图像。 Now, in our
main.cpp
:现在,在我们的
main.cpp
:
#include "mytimer.h"
int main(int argc, char *argv[])
{
qmlRegisterType<ImageItem>("ImageItem",1,0,"ImageItem");
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
ImageItem *fImage = new ImageItem();
MyTimer *timer = new MyTimer(fImage);
fImage->setImageURL(":fruit.jpg");
engine.rootContext()->setContextProperty("cpp_imageURL", fImage);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.