QML 对象不更新显示

Posted

技术标签:

【中文标题】QML 对象不更新显示【英文标题】:QML object does not update on display 【发布时间】:2020-12-22 22:08:44 【问题描述】:

我用 C++ 创建了一个 QML 对象。在我的主要方法中,我可以设置我在自定义 QML 对象中定义的各种属性。从 main 方法设置时,各种属性按预期显示。当我从我的更新方法中设置属性时,显示永远不会更新。我已经验证了我的自定义 QML 对象中的关联方法正在接收我传递给它的值。为什么我的显示器不会更新?

ma​​in.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "horizontalBarGraph.h"
#include "speedometer.h"
#include "test.h"
#include <QTimer>
#include <QDebug>

//QObject *item = NULL;
static HorizontalBarGraph *ptrOilTemp = nullptr;
static int value = 0;


int update()

    //qInfo() << "update() called.";


    if(value > ptrOilTemp->getMaxValue())
    
        value = 0;
    
    ptrOilTemp->setActualValue(value);
    qInfo() << "value = " << value;

    value++;

    //ptrOilTemp->setUnits("Test");

    return 0;


int main(int argc, char *argv[])

    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);

    qmlRegisterType<Speedometer>("com.ulasdikme.speedometer",1,0,"Speedometer");
    qmlRegisterType<HorizontalBarGraph>("com.kubie.horizontalBarGraph", 1, 0, "HorizontalBarGraph");
    qmlRegisterType<Test>("com.kubie.test", 1, 0, "Test");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    //item = engine.rootObjects().at(0)->findChild<QQuickItem*>("testing");

    QObject *object = engine.rootObjects()[0];
    QObject *oilTemp = object->findChild<QObject*>("oilTemp");
    QObject *oilPressure = object->findChild<QObject*>("oilPressure");
    QObject *coolantTemp = object->findChild<QObject*>("coolantTemp");
    QObject *coolantPressure = object->findChild<QObject*>("coolantPressure");
    QObject *intakeAirTemp = object->findChild<QObject*>("intakeAirTemp");
    QObject *engineRPM = object->findChild<QObject*>("engineRPM");

    //HorizontalBarGraph *ptrOilTemp = qobject_cast<HorizontalBarGraph*>(oilTemp);
    ptrOilTemp = qobject_cast<HorizontalBarGraph*>(oilTemp);
    HorizontalBarGraph *ptrOilPressure = qobject_cast<HorizontalBarGraph*>(oilPressure);
    HorizontalBarGraph *ptrCoolantTemp = qobject_cast<HorizontalBarGraph*>(coolantTemp);
    HorizontalBarGraph *ptrCoolantPressure = qobject_cast<HorizontalBarGraph*>(coolantPressure);
    HorizontalBarGraph *ptrIntakeAirTemp = qobject_cast<HorizontalBarGraph*>(intakeAirTemp);
    HorizontalBarGraph *ptrEngineRPM = qobject_cast<HorizontalBarGraph*>(engineRPM);

    qreal val1 = 0;
    //qreal val2 = 25;
    qreal val3 = 100;

    QString degF(QChar(0x00b0));
    degF += "F";

    ptrOilTemp->setSensorName("Oil Temp");
    ptrOilTemp->setUnits(degF);
    ptrOilTemp->setMinValue(val1);
    ptrOilTemp->setMaxValue(val3);
    //ptrOilTemp->setActualValue(val2);

    ptrOilPressure->setSensorName("Oil Press");
    ptrOilPressure->setUnits("PSI");

    ptrCoolantTemp->setSensorName("Coolant Temp");
    ptrCoolantTemp->setUnits(degF);

    ptrCoolantPressure->setSensorName("Coolant Press");
    ptrCoolantPressure->setUnits("PSI");

    ptrIntakeAirTemp->setSensorName("Intake Air Temp");
    ptrIntakeAirTemp->setUnits(degF);

    ptrEngineRPM->setSensorName("");
    ptrEngineRPM->setUnits("RPM");

    qInfo() << "Initializing timer.";
    QTimer timer;// = new QTimer(this);
    QObject::connect(&timer, &QTimer::timeout, update);
    timer.start(100);



    return app.exec();

horizo​​ntalBarGraph.cpp

#include <QPainter>
#include "horizontalBarGraph.h"

HorizontalBarGraph::HorizontalBarGraph(QQuickItem *parent)
    :QQuickPaintedItem(parent),
      _horizontalBarGraphWidth(260),
      _horizontalBarGraphHeight(75),
      _minValue(0),
      _maxValue(0),
      _actualValue(0),
      _sensorName("Sensor Name"),
      _units("Units")




void HorizontalBarGraph::paint(QPainter *painter)

    QRectF rect = this->boundingRect();
    painter->setRenderHint(QPainter::Antialiasing);
    QPen pen = painter->pen();
    pen.setCapStyle(Qt::FlatCap);

    QFont bottomFont("Arial", 14, QFont::Bold);
    QFont topFont("Arial", 16, QFont::Bold);
    QColor gray1(225, 225, 225);
    QColor gray2(200, 200, 200);
    QColor gray3(175, 175, 175);
    QColor gray4(100, 100, 100);

    //minValue, actualValue, maxValue
    painter->save();
    painter->setFont(bottomFont);
    pen.setColor(gray1);
    painter->setPen(pen);
    painter->drawText(rect.adjusted(0, 50, -210, 0), Qt::AlignHCenter | Qt::AlignBottom, QString::number((_minValue), 'f', 0)); //Draws minValue
    painter->drawText(rect.adjusted(210, 50, 0, 0), Qt::AlignHCenter | Qt::AlignBottom, QString::number((_maxValue), 'f', 0)); //Draws maxValue
    painter->drawText(rect.adjusted(0, 50, 0, 0), Qt::AlignHCenter | Qt::AlignBottom, QString::number((_actualValue), 'f', 1));
    //pen.setStyle(Qt::DotLine); //Next 3 lines were used to show the bounding rectangle for a drawText object
    //painter->setPen(pen);
    //painter->drawRect(rect.adjusted(0, 50, -150, 0));
    painter->restore();

    //Bar chart background
    painter->save();
    painter->fillRect(rect.adjusted(25, 35, -25, -25), gray1);
    painter->restore();

    //Lo
    painter->save();
    painter->fillRect(rect.adjusted(25, 35, -185, -25), gray2);
    painter->restore();

    //LoLo
    painter->save();
    painter->fillRect(rect.adjusted(25, 35, -210, -25), gray3);
    painter->restore();

    //Hi
    painter->save();
    painter->fillRect(rect.adjusted(185, 35, -25, -25), gray2);
    painter->restore();

    //HiHi
    painter->save();
    painter->fillRect(rect.adjusted(210, 35, -25, -25), gray3);
    painter->restore();

    //Sensor name, Units
    painter->save();
    painter->setFont(topFont);
    pen.setColor(gray1);
    painter->setPen(pen);
    painter->drawText(rect.adjusted(25, 0, -50, -40), Qt::AlignLeft | Qt::AlignTop, _sensorName); //Draws sensor name
    painter->drawText(rect.adjusted(50, 0, -25, -40), Qt::AlignRight | Qt::AlignTop, _units); //Draws units
    painter->restore();

    //Arrow
//    painter->save();
//    static const QPointF points[3] = 
//        QPointF(17.5, 27.5),
//        QPointF(32.5, 27.5),
//        QPointF(25.0, 42.5)
//    ;
//    painter->drawPolygon(points, 3);
//    painter->restore();
    painter->save();
    QPainterPath path;
    qreal x = scale(_actualValue, _minValue, _maxValue, 25, 235);
    //path.moveTo(17.5, 27.5);
    //path.lineTo(32.5, 27.5);
    //path.lineTo(25.0, 42.5);
    path.moveTo(x - 7.5, 27.5);
    path.lineTo(x + 7.5, 27.5);
    path.lineTo(x, 42.5);
    path.closeSubpath();
    painter->fillPath(path, gray4);
    painter->restore();





qreal HorizontalBarGraph::getHorizontalBarGraphWidth()

    return _horizontalBarGraphWidth;



qreal HorizontalBarGraph::getHorizontalBarGraphHeight()

    return _horizontalBarGraphHeight;



qreal HorizontalBarGraph::getMinValue()

    return _minValue;



qreal HorizontalBarGraph::getMaxValue()

    return _maxValue;



qreal HorizontalBarGraph::getActualValue()

    return _actualValue;



QString HorizontalBarGraph::getSensorName()

    return _sensorName;



QString HorizontalBarGraph::getUnits()

    return _units;



void HorizontalBarGraph::setHorizontalBarGraphWidth(qreal width)

    if(_horizontalBarGraphWidth == width)
        return;

    _horizontalBarGraphWidth = width;

    emit widthChanged();



void HorizontalBarGraph::setHorizontalBarGraphHeight(qreal height)

    if(_horizontalBarGraphHeight == height)
        return;

    _horizontalBarGraphHeight = height;

    emit heightChanged();



void HorizontalBarGraph::setMinValue(qreal minValue)

    if(_minValue == minValue)
        return;

    _minValue = minValue;

    emit minValueChanged();



void HorizontalBarGraph::setMaxValue(qreal maxValue)

    if(_maxValue == maxValue)
        return;

    _maxValue = maxValue;

    emit maxValueChanged();



void HorizontalBarGraph::setActualValue(qreal actualValue)

    if(_actualValue == actualValue)
        return;

    _actualValue = actualValue;

    emit actualValueChanged();



void HorizontalBarGraph::setSensorName(QString sensorName)

    if(_sensorName == sensorName)
        return;

    _sensorName = sensorName;

    emit sensorNameChanged();



void HorizontalBarGraph::setUnits(QString units)

    if(_units == units)
        return;

    _units = units;

    emit unitsChanged();



qreal HorizontalBarGraph::scale(qreal input, qreal inputMin, qreal inputMax, qreal outputMin, qreal outputMax)

    qreal output = (outputMax - outputMin) * (input - inputMin) / (inputMax - inputMin) + outputMin;
    if(output > outputMax)
        output = outputMax;

    if(output < outputMin)
        output = outputMin;

    return output;

horizo​​ntalBarGraph.h

#ifndef HORIZONTALBARGRAPH_H
#define HORIZONTALBARGRAPH_H

#include <QObject>
#include <QQuickPaintedItem>

class HorizontalBarGraph : public QQuickPaintedItem

    Q_OBJECT

    Q_PROPERTY(qreal horizontalBarGraphWidth READ getHorizontalBarGraphWidth WRITE setHorizontalBarGraphWidth NOTIFY horizontalBarGraphWidthChanged)
    Q_PROPERTY(qreal horizontalBarGraphHeight READ getHorizontalBarGraphHeight WRITE setHorizontalBarGraphHeight NOTIFY horizontalBarGraphHeightChanged)
    Q_PROPERTY(qreal minValue READ getMinValue WRITE setMinValue NOTIFY minValueChanged)
    Q_PROPERTY(qreal maxValue READ getMaxValue WRITE setMaxValue NOTIFY maxValueChanged)
    Q_PROPERTY(qreal actualValue READ getActualValue WRITE setActualValue NOTIFY actualValueChanged)
    Q_PROPERTY(QString sensorName READ getSensorName WRITE setSensorName NOTIFY sensorNameChanged)
    Q_PROPERTY(QString units READ getUnits WRITE setUnits NOTIFY unitsChanged)


public:
    HorizontalBarGraph(QQuickItem *parent = 0);
    virtual void paint(QPainter *painter);

    qreal   getHorizontalBarGraphWidth();
    qreal   getHorizontalBarGraphHeight();
    qreal   getMinValue();
    qreal   getMaxValue();
    qreal   getActualValue();
    QString getSensorName();
    QString getUnits();

    void    setHorizontalBarGraphWidth(qreal width);
    void    setHorizontalBarGraphHeight(qreal height);
    void    setMinValue(qreal minValue);
    void    setMaxValue(qreal maxValue);
    void    setActualValue(qreal actualValue);
    void    setSensorName(QString sensorName);
    void    setUnits(QString units);

signals:
    void    horizontalBarGraphWidthChanged();
    void    horizontalBarGraphHeightChanged();
    void    minValueChanged();
    void    maxValueChanged();
    void    actualValueChanged();
    void    sensorNameChanged();
    void    unitsChanged();

private:
    qreal   _horizontalBarGraphWidth;
    qreal   _horizontalBarGraphHeight;
    qreal   _minValue;
    qreal   _maxValue;
    qreal   _actualValue;
    QString _sensorName;
    QString _units;
    qreal   scale(qreal input, qreal inputMin, qreal inputMax, qreal outputMin, qreal outputMax);

;

#endif // HORIZONTALBARGRAPH_H

ma​​in.qml

import QtQuick 2.11
import QtQuick.Window 2.11
import com.kubie.horizontalBarGraph 1.0

Window 
    id: window
    visible: true
    width: 800
    height: 480
    title: qsTr("REDNEKSLDHLR")
    color: "black"

//    Rectangle
//    
//        width: 260
//        height: 75
//        color: "#7a0505"
//        anchors.bottom: parent.bottom
//        anchors.bottomMargin: 0
//        anchors.left: parent.left
//        anchors.leftMargin: 0
//    

    HorizontalBarGraph 
        objectName: "oilTemp"
        anchors.left: parent.left
        anchors.leftMargin: 0
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 0
        width: horizontalBarGraphWidth
        height: horizontalBarGraphHeight
    

    HorizontalBarGraph 
        objectName: "oilPressure"
        anchors.left: parent.left
        anchors.leftMargin: 0
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 75
        width: horizontalBarGraphWidth
        height: horizontalBarGraphHeight
    

    HorizontalBarGraph 
        objectName: "coolantTemp"
        anchors.right: parent.right
        anchors.rightMargin: 0
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 0
        width: horizontalBarGraphWidth
        height: horizontalBarGraphHeight
    

    HorizontalBarGraph 
        objectName: "coolantPressure"
        anchors.right: parent.right
        anchors.rightMargin: 0
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 75
        width: horizontalBarGraphWidth
        height: horizontalBarGraphHeight
    

    HorizontalBarGraph 
        objectName: "intakeAirTemp"
        anchors.left: parent.left
        anchors.leftMargin: parent.width / 2 - width / 2;
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 0
        width: horizontalBarGraphWidth
        height: horizontalBarGraphHeight
    

        HorizontalBarGraph 
            objectName: "engineRPM"
            anchors.left: parent.left
            anchors.leftMargin: parent.width / 2 - width / 2;
            anchors.bottom: parent.bottom
            anchors.bottomMargin: 75
            width: horizontalBarGraphWidth
            height: horizontalBarGraphHeight
    



【问题讨论】:

请提供minimal reproducible example。 QGuiApplication 在哪里? @eyllanesc 帖子已更新为包含所有代码。 就是这样......我遵循的示例从未称为更新 - 我认为这有点奇怪。我从来没有把两个和两个放在一起。您可以发布作为答案,我会接受吗? 【参考方案1】:

您必须使用update() 方法来重新绘制GUI,因此每次修改用于绘制的属性时都必须调用它。举例:

void HorizontalBarGraph::setActualValue(qreal actualValue)      
    if(_actualValue == actualValue)         
        return;      
    _actualValue = actualValue;     
    update();  
    emit actualValueChanged(); 

【讨论】:

以上是关于QML 对象不更新显示的主要内容,如果未能解决你的问题,请参考以下文章

在 QML 中为 MapQuickItem 设置位置更新动画

从 C++ 更新 QML Window 属性标志

在QML :: Image视图上更新多个QImages仅显示最后发送的QImages

QML 阻止 ListView 委托一直更新

在 QML 中更新对 var 属性的绑定

在 QML 上异步更新多个 QQuickPaintedItem