从C ++更改QML对象值

时间:2018-08-13 14:17:06

标签: c++ qt qml

我创建了一个类似QML的类

import QtQuick 2.2
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Extras 1.4

Rectangle {
    width: 80
    height: 200
    property double myVal: 15

    Timer {
        running: true
        repeat: true
        interval: 1
        onTriggered: gauge.value = myVal
    }

    Gauge {
        objectName: "gauge"
        id: gauge
        anchors.fill: parent
        anchors.margins: 10

        value: myVal
        Behavior on value {
            NumberAnimation {
                duration: 1000
            }
        }

        style: GaugeStyle {
            valueBar: Rectangle {
                implicitWidth: 16
                color: Qt.rgba(gauge.value / gauge.maximumValue, 0, 1 - gauge.value / gauge.maximumValue, 1)
            }
        }
    }
}

,我想从我的c ++文件中更改值。为此,我创建了一个方法setDataToGauge(),该方法类似于

void MainWindow::setDataToGauge(double newVal){

    QQmlApplicationEngine engine;
    QQmlComponent component(&engine, QUrl::fromLocalFile("gauge.qml"));
    QObject object = component.create();
    QObject *myGauge = object->findChild<QObject*>("gauge");

    if(myGauge){
        myGauge->setProperty("value",newVal);
        qDebug() << myGauge->property("value");

    }

}

这个。但是,它不会更改仪表的值。我尝试了不同的方法,但是找不到解决方案。当我放下

    Behavior on value {
        NumberAnimation {
            duration: 1000
        }
    }

这部分来自QML文件的值正在更改,但仪表视图未更改。 另外,我正在添加我的c ++文件的完整代码

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QDateTime>
#include <QtQuickWidgets/QQuickWidget>
#include <QtQml>
#include <QObject>

QObject *object;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    m_serial(new QSerialPort(this))
{
    ui->setupUi(this);

    ui->gaugeWidget->setSource(QUrl::fromLocalFile("gauge.qml"));
    ui->gaugeWidget->setUpdatesEnabled(true);

    QQmlApplicationEngine engine;
    QQmlComponent component(&engine, QUrl::fromLocalFile("gauge.qml"));
    object = component.create();

    setDataToGauge(60.0);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::setDataToGauge(double newVal){

    QObject *myGauge = object->findChild<QObject*>("gauge");

    if(myGauge){
        QQmlProperty::write(myGauge, "value", newVal);
        qDebug() << myGauge->property("value");
}

}

那里是什么问题?

1 个答案:

答案 0 :(得分:1)

在尝试解决方案时,您正在创建另一个仪表,而该仪表不显示,因为QQmlApplicationEngine是一个局部变量,在执行完成后将被删除,另外QQmlApplicationEngine期望{ {1}}或Window,而不是像ApplicationWindow这样的Item

另一方面,建议使用Rectangle存储.qml,因为否则,每次编译可执行文件时,都必须复制它们。

也不建议从C ++访问QML对象,最好使用qresource将C ++对象导出到QML。

一个简单的解决方案是创建一个信号,该信号通过setContextProperty() ::

连接

*。h

Connections

*。cpp

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void setDataToGauge(double newVal);
signals:
    void dataGaugeChanged(double dataToGauge); // signal
private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

gauge.qml

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QQmlEngine>
#include <QQmlContext>


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->gaugeWidget->engine()->rootContext()->setContextProperty("MainWindow", this);
    ui->gaugeWidget->setSource(QUrl("qrc:/gauge.qml"));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::setDataToGauge(double newVal){
    emit dataGaugeChanged(newVal);
}

另一种选择是创建一个import QtQuick 2.2 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import QtQuick.Extras 1.4 Rectangle { width: 80 height: 200 Gauge { id: gauge anchors.fill: parent anchors.margins: 10 Behavior on value { NumberAnimation { duration: 1000 } } style: GaugeStyle { valueBar: Rectangle { implicitWidth: 16 color: Qt.rgba(gauge.value / gauge.maximumValue, 0, 1 - gauge.value / gauge.maximumValue, 1) } } } Connections{ target: MainWindow onDataGaugeChanged: gauge.value = dataToGauge } } 并进行绑定:

*。h

Q_PROPERTY

*。cpp

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
    Q_PROPERTY(double dataGauge READ dataGauge WRITE setDataGauge NOTIFY dataGaugeChanged)

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    double dataGauge() const;
    void setDataGauge(double dataGauge);
signals:
    void dataGaugeChanged();
private:
    Ui::MainWindow *ui;
    double mDataGauge;
};

#endif // MAINWINDOW_H

*。qml

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QQmlEngine>
#include <QQmlContext>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->gaugeWidget->engine()->rootContext()->setContextProperty("MainWindow", this);
    ui->gaugeWidget->setSource(QUrl("qrc:/gauge.qml"));
}

MainWindow::~MainWindow()
{
    delete ui;
}

double MainWindow::dataGauge() const
{
    return mDataGauge;
}

void MainWindow::setDataGauge(double dataGauge)
{
    if(mDataGauge == dataGauge)
        return;
    mDataGauge = dataGauge;
    emit dataGaugeChanged();
}

这两个解决方案都可以在下面的link中找到。