简体   繁体   English

Qml 图像不会在源更改和信号接收时刷新

[英]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.我上传了下面的每一个源代码。

在此处输入图片说明

fruit_swap.pro Fruit_swap.pro

/* 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

imageitem.h图像项.h

/* 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

imageitem.cpp图像项.cpp

/* 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;
}

main.cpp主程序

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

FruitFrame.qml水果框架.qml

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

main.qml主文件

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();
        }
    }
}

Application Output应用输出

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.例如,如果您使用QTimerQThread ,您将检查图像是否正确更新。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM