Refreshing a QML embedded within QQuickWidget in a QWidget application
-
Hey,
I have some 'analog' gauge to create and it appears that the best way to create them is using QtQuick. However I'm working within a qWidget environment, where the gauge's value is determined and sent to the view by a counter.
I managed to embedded my qml view in a QQuickWidget and to bind qml and qWidget, according to a connections qml object and some signals/slots. The QQuickWidget is in a layout.
I add a c++ function which is called every 100ms for cyclic, actions like the incrementation of a counter which has to simulate the gauge evolution.
During the runtime, all looks good (qml text refreshed by the c++ counter incrementation) but after some iterations, all is frozen in the qml. And I really don't know why. I tried to call some update() or repaint() functions or to reload the qml source, nothing happens...
Exists it a method to force it to refresh the printed data ?
Could you give me an hand please ?piece of my code below,
Thank you
homePage.cpp
#include "cpagehome.h" #include <QGridLayout> #include <QtQuick> #include "pagemanager.h" CPageHome::CPageHome(PageManager * parent) { // Save address of parent m_parent = parent; QQuickWidget * mp_view = new QQuickWidget; mp_data = new Data(); //qmlRegisterType<Data>("DATA", 1, 0, "Data"); mp_view->rootContext()->setContextProperty("file", mp_data); mp_data->setValue(100); // mp_data->set_i_value(10); // mp_view->rootContext()->setContextProperty("mpData",mp_data); mp_view->setAttribute(Qt::WA_AlwaysStackOnTop, true); mp_view->setAttribute(Qt::WA_TranslucentBackground, true); mp_view->setClearColor(Qt::transparent); mp_view->setResizeMode(QQuickWidget::SizeRootObjectToView);/* Le QML fit au qwidget */ mp_view->setSource(QUrl("qrc:/testQML.qml")); // Add widget to the layout m_layout = new QGridLayout(this); m_layout->addWidget(mp_view); } void CPageHome::onActive(int activePage) { /* called every 100 ms */ static int hi_value = mp_data->getValue(); mp_data->setValue(hi_value); // mp_view->engine()->clearComponentCache(); // mp_view->setSource(QUrl(QStringLiteral("qrc:/testQML.qml"))); /* if (hi_value % 2 == 0) { m_parent->showButtons(100); } */ qDebug() << "mp_data: " << mp_data->getValue() ; //mp_view->rootContext()->setContextProperty("mpData",mp_data); //mp_view->setSource(QUrl(QStringLiteral("qrc:/testQML.qml"))); //mp_view->repaint(); //mp_view->update(); //mp_view->resize(10*hi_value,10*hi_value); //m_layout->removeWidget(mp_view); //m_layout->addWidget(btn,1,2); //mp_view->adjustSize(); //mp_view->updateGeometry(); hi_value +=1; } CPageHome::~CPageHome() { }
datafile.cpp, used to transfer data between qml and qWidget
#include "data.h" Data::Data() { mi_value = 0; } Data::~Data() { } int Data::getValue(void) { return mi_value; } void Data::setValue(int oi_value) { mi_value = oi_value; emit valueChanged(mi_value); }
datafile.h
#ifndef DATA_H #define DATA_H #include <QObject> #include <QWidget> class Data : public QObject { Q_OBJECT Q_PROPERTY(int value READ getValue WRITE setValue NOTIFY valueChanged) public: Data(); virtual ~Data(); Q_INVOKABLE int getValue(void); Q_INVOKABLE void setValue(int oi_value); signals: void valueChanged(int oi_value); private: int mi_value; }; #endif // DATA_H
testQML.qml
import QtQuick 2.4 import QtQuick.Controls 1.0 Item { width: 800 height: 480 Rectangle{ id: rect anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter height: parent.height/3 width: height color: 'coral' Text{ id: textBox text: file.getValue() onTextChanged: { textBox.text = connection.newValue; } Connections{ id: connection target: file property int newValue: 1000 onValueChanged: { console.log("oi_value : " + oi_value); newValue = oi_value; textBox.text = oi_value + ''; } } } } }
A QTimer in the pageManager is launched at the beginning, and generates signals to call onActive function.
-
hi @Alexiss and welcome
one thing jumps to my mind, you should actually check if the value differs - that's the standard way to do it, and you should check if the setValue function is still called and just the Ui doesn't display the change.
void Data::setValue(int oi_value) { qDebug() << Q_FUNC_INFO << oi_value << "same value?" << (mi_value == oi_value); if(mi_value == oi_value) return; mi_value = oi_value; emit valueChanged(mi_value); }