I created a QML class like
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)
}
}
}
}
and I want to change value from my c++ file. To do this, I created a method which is setDataToGauge() and this method is like
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");
}
}
this. However, it doesn't change the value of gauge. I tried different methods but it couldn't find the solution. When I drop
Behavior on value {
NumberAnimation {
duration: 1000
}
}
this part from QML file value is changing but view of gauge is not changing. Also, I am adding to full code of my c++ file
#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");
}
}
What is the problem in there?
In your attempt of solution you are creating another gauge, and that gauge is not shown because the QQmlApplicationEngine
is a local variable that will be deleted when it finishes executing, in addition QQmlApplicationEngine
expects a Window
or ApplicationWindow
, not an Item
like Rectangle
.
On the other hand it is advisable to use a qresource
to store the .qml because otherwise you will have to copy them every time you compile the side of your executable.
It is also not recommended to access QML objects from C ++, it is better to export a C ++ object to QML using setContextProperty()
.
A simple solution is to create a signal, the signal is connected through Connections
::
*.h
#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
*.cpp
#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);
}
gauge.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
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
}
}
Another option is to create a Q_PROPERTY
and make a binding:
*.h
#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
*.cpp
#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();
}
*.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
Gauge {
id: gauge
anchors.fill: parent
anchors.margins: 10
value: MainWindow.dataGauge // binding
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)
}
}
}
}
Both solutions can be found in the following link .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.