I am trying to read a value from mysql db through Qt and push the value to QML(specifically to a CircularGauge dial). I am successfully able to read the db value and print it to console in Qt. When I try to expose the value to QML, it is not getting reflected in QML dashboard. The following are my files:-
qml.h
#ifndef QML_H
#define QML_H
#include <QObject>
#include <QVariant>
#include <QDebug>
#include <QTime>
#include <qquickimageprovider.h>
#include <QImage>
#include <QString>
/*------------------------------SPEED------------------------------*/
class Speed : public QObject
{
Q_OBJECT
Q_PROPERTY(double velocity MEMBER m_velocity NOTIFY velocityChanged)
public:
Speed(QObject* parent = nullptr);
virtual ~Speed() {}
const double MPS2KNOTS = 1.94;
void velocityCallback();
private slots:
void updateVelocity(double x);
signals:
void velocityChanged();
void receivedVelocity(double x);
private:
double m_velocity = 0.0;
};
#endif // QML_H
qml.cpp
#include <QSqlDatabase>
#include <QSqlQueryModel>
#include <QSqlQuery>
#include <QDebug>
#include <qml.h>
Speed::Speed(QObject*)
{
connect(this, SIGNAL(receivedVelocity(double)), this, SLOT(updateVelocity(double)));
}
void Speed::velocityCallback()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("localhost");
db.setDatabaseName("sim_speed");
db.setUserName("administrator");
db.setPassword("test");
bool ok = db.open();
double x;
QSqlQuery query;
//while (ok) {
query.prepare("SELECT speed FROM speed");
query.exec();
if (query.next()) {
x= query.value(0).toDouble();
}
qDebug() << "Value is";
qDebug() << ok;
qDebug() << x;
receivedVelocity(x);
//}
}
void Speed::updateVelocity(double x)
{
m_velocity = x;
emit velocityChanged();
qDebug() << m_velocity;
}
main.cpp
#include <functional>
#include <QCoreApplication>
#include <QObject>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QUrl>
#include <QString>
#include <QQuickWindow>
#include <QtQml>
#include <QtConcurrent/QtConcurrent>
#include <QFuture>
#include <QFutureWatcher>
#include <qml.h>
#include <QQmlProperty>
#include <thread> // std::thread
#include <QDebug>
#include <QCoreApplication>
#include <QTextStream>
#include <QFile>
using namespace std;
int main(int argc, char** argv)
{
//std::thread dbret(velocityCallback());
QGuiApplication app(argc, argv);
Speed speedqml(&app);
//QObject::connect(&app, &QCoreApplication::aboutToQuit, [](){});
QQmlApplicationEngine engine(&app);
engine.rootContext()->setContextProperty("velocity", &speedqml);
Speed sp;
sp.velocityCallback();
engine.load(QUrl("qrc:/main.qml"));
// std::thread dbret(mainn);
//dbret.join();
return app.exec();
}
main.qml
import QtMultimedia 5.8
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Extras 1.4
import QtSensors 5.10
//import Ros 1.0
Window {
visible: true
width: 1920
height: 1080
title: qsTr("Gazebo")
Rectangle {
id: speedometer
x: 10
y: 10
width: 150
height:150
radius: width*0.5
opacity: 0.5
color: "black"
CircularGauge {
id:gauge
value: velocity.velocity
maximumValue : 10
x:10
y:10
width:150
height:150
anchors.centerIn: parent
style: CircularGaugeStyle {
labelStepSize: 0.5
tickmarkStepSize: 0.5
}
Text {
text: "Speed:"+velocity.velocity+"m/s"
anchors.top:parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
}
Behavior on value {
NumberAnimation {
duration: 1000
}
}
MouseArea {
anchors.fill: parent
onClicked: {
// tachometer.visible = false
// speedometer.visible = false
// compassdial.visible = false
// altimeterback.visible = false
// ammeter.visible = false
// voltmeter.visible = false
// throttlegauge.visible = false
// dashboard.visible = true
}
}
}
}
}
This question already has answers here:
C++ variable scope
(2 answers)
Closed 3 years ago.
I am using an QML in Qt.
Having two classes,
Board class and TimerUi class.
QML calls the Board::start()
The Board::start() calls the TimerUi::startTimer().
The problem is, QTimer in TimerUi class does not start at all. The main thing i wanted, is to leave all timer based functions in one place, and have ability to call it from any class.
If i call the TimerUi::startTimer() directly from QML - it works.
Can someone explain me please, where is my error?
main.cpp
#include <QDebug>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QSettings>
#include <QString>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "board.h"
int main(int argc, char *argv[]) {
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
QGuiApplication app(argc, argv);
QCoreApplication::setOrganizationName("Test");
QCoreApplication::setOrganizationDomain("test");
QCoreApplication::setApplicationName("Test");
qmlRegisterType<Board>("io.qt.board", 1, 0, "Board");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/Main.qml")));
return app.exec();
}
Main.qml
import QtQuick 2.12
import QtQuick.Controls 2.9
import io.qt.board 1.0
import QtQuick.Controls.Imagine 2.4
import QtQuick.Window 2.3
import QtWebEngine 1.0
ApplicationWindow {
id: window
visible: true
width: 800
height: 600
title: qsTr("Stack")
// Init Board
Board {id: board}
// Init
Component.onCompleted: {
board.init();
}
RoundButton {
id: startButton
x: 14
y: 26
width: 230
height: 230
text: !board.isStarted ? "Start" : "Stop"
font.pointSize: 30
background: Image { source: board.isStarted? "/stop.png" : "/start.png"; }
onClicked: board.start()
contentItem: Text {
text: startButton.text
font: startButton.font
opacity: enabled ? 1.0 : 0.3
color: "black"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
board.h
#ifndef BOARD_H
#define BOARD_H
#include <QObject>
#include <QString>
#include <QTimer>
class Board : public QObject {
Q_OBJECT
Q_PROPERTY(bool isStarted READ isStarted NOTIFY isStartedChanged WRITE
setIsStarted)
public:
explicit Board(QObject *parent = nullptr);
bool isStarted();
Q_INVOKABLE void init();
Q_INVOKABLE void start();
signals:
void isStartedChanged(bool b_isStarted);
public slots:
private:
QString b_start;
static bool b_isStarted;
};
#endif // BOARD_H
board.cpp
#include "board.h"
#include "timerui.h"
#include <QDebug>
#include <QString>
#include <QTimer>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
bool Board::b_isStarted = 0;
bool Board::isStarted() { return b_isStarted; }
void Board::setIsStarted(bool &isStarted) {
b_isStarted = isStarted;
emit isStartedChanged(isStarted);
}
Board::Board(QObject *parent) : QObject(parent) {}
void Board::init() {
qDebug() << "Some init";
}
// Start
void Board::start() {
TimerUi timerUi;
if (!b_isStarted) {
qDebug() << "isStarted";
b_isStarted = true;
timerUi.startTimer(); // <-- Here
}
emit isStartedChanged(b_isStarted);
}
timerui.h
#ifndef TIMERUI_H
#define TIMERUI_H
#include <QObject>
#include <QString>
#include <QTimer>
class TimerUi : public QObject {
Q_OBJECT
QTimer *m_timer;
Q_PROPERTY(int minTimer READ minTimer NOTIFY minTimerChanged())
public:
explicit TimerUi(QObject *parent = nullptr);
Q_INVOKABLE void startTimer(QObject *target);
int minTimer();
signals:
void minTimerChanged();
public slots:
void setTime();
private:
static int m_minTimer;
};
#endif // TIMERUI_H
timer.cpp
#include "timerui.h"
#include <QDebug>
#include <QSettings>
#include <QTimer>
int TimerUi::m_minTimer = 0;
TimerUi::TimerUi(QObject *parent) : QObject(parent) {}
int TimerUi::minTimer() { return m_minTimer; }
void TimerUi::startTimer() {
m_minTimer = 0;
// Timer
QTimer *m_timer = new QTimer(this);
connect(m_timer, SIGNAL(timeout()), this, SLOT(setTime()));
m_timer->start(1000);
}
void TimerUi::setTime() {
minTimer++;
qDebug() << "Hello " << minTimer;
emit minTimerChanged();
}
Thanks.
You declare your TimerUI in the local scope of Board::start, it is destroyed when the function end. That is probably where your problem come from.
I have got three classes created in C++ as Window, PropertyList and MyParams and I want to pass PropertyList and MyParams these two classes to qml.
class Window
{
public:
PropertyList* getPropertyList();
private:
PropertyList* propertyList;
};
class PropertyList : public QObject
{
Q_OBJECT
public:
MyParams* getMyParams();
Q_INVOKABLE void test();
private:
MyParams* myParams;
};
class MyParams : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE void test();
};
int main(int argc, char *argv[])
{
Window* window = new Window();
PropertyList* propertyList = window->getPropertyList();
MyParams* myParam = propertyList->getMyParams();
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty(QStringLiteral("myParams"), myParam);
engine.rootContext()->setContextProperty(QStringLiteral("propertyList"), propertyList);
}
Why does this work:
engine.rootContext()->setContextProperty(QStringLiteral("propertyList"), propertyList);
And this fail:
engine.rootContext()->setContextProperty(QStringLiteral("myParams"), myParam);
Is it because I declare PropertyList as Q_OBJECT? And how can I fix this? Thanks a lot.
propertyList.test() can be called succesfully while myParams.test() cannot be called and crashed the qml.
I cannot see any problems in your code example, because the sample is not complete (Consider: https://stackoverflow.com/help/reprex).
Nevertheless I implemented a solution for you. I hope it will help. (Warning: there will be memory leaks around class Window, but it should helpt to understand C++ and Qml binding)
Here is your PropertyList.h:
#ifndef PROPERTYLIST_H
#define PROPERTYLIST_H
#include "myparams.h"
#include <QObject>
class PropertyList : public QObject
{
Q_OBJECT
public:
explicit PropertyList(QObject *parent = nullptr) : QObject (parent) { }
MyParams* getMyParams()
{
return myParams;
}
Q_INVOKABLE void test()
{
qDebug() << "PropertyList test";
}
private:
MyParams* myParams = new MyParams();
};
#endif // PROPERTYLIST_H
Here is your MyParams.h:
#ifndef MYPARAMS_H
#define MYPARAMS_H
#include <QObject>
#include <QDebug>
class MyParams : public QObject
{
Q_OBJECT
public:
explicit MyParams(QObject *parent = nullptr) : QObject (parent) { }
Q_INVOKABLE void test()
{
qDebug() << "MyParams test";
}
};
#endif // MYPARAMS_H
Here is your main.cpp:
#include "propertylist.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlEngine>
#include <QQmlContext>
#include <QDebug>
class Window
{
public:
PropertyList* getPropertyList()
{
return propertyList;
}
private:
PropertyList* propertyList = new PropertyList(nullptr);
};
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
Window* window = new Window();
PropertyList* propertyList = window->getPropertyList();
MyParams* myParam = propertyList->getMyParams();
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty(QStringLiteral("myParams"), myParam);
engine.rootContext()->setContextProperty(QStringLiteral("propertyList"), propertyList);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
{
return -1;
}
return app.exec();
}
Here is your main.qml:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
ColumnLayout {
anchors.centerIn: parent
Button {
text: "myParams"
onClicked: {
myParams.test()
}
}
Button {
text: "propertyList"
onClicked: {
propertyList.test()
}
}
}
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I know this question as been multiple times . I have browsed and trying for 5 days to link my C++ signal to a QML slot via Connections in QML . Here is my code at the moment and I don't understand why I always get :Cannot assign to non-existent property "ondashsetupChanged"
Please tell me what i am doing wrong ? The complete code is here :
https://github.com/BastianGschrey/PowerTune/tree/Simplification
Here is my code:
my main.cpp :
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QtQml>
#include "connect.h"
int main(int argc, char *argv[])
{
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
QApplication app(argc, argv);
app.setOrganizationName("Power-Tune");
app.setOrganizationDomain("power-tune.org");
app.setApplicationName("PowerTune");
QQmlApplicationEngine engine;
qmlRegisterType<Connect>("com.powertune", 1, 0, "ConnectObject");
engine.rootContext()->setContextProperty("Connect", new Connect(&engine));
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
connect.cpp :
#include "datalogger.h"
#include "connect.h"
#include "calculations.h"
#include "sensors.h"
#include "AdaptronicSelect.h"
#include "AdaptronicCAN.h"
#include "Apexi.h"
#include "HaltechCAN.h"
#include "Nissanconsult.h"
#include "obd.h"
#include "AdaptronicCAN.h"
#include "HaltechCAN.h"
#include "Apexi.h"
#include "AdaptronicSelect.h"
#include "dashboard.h"
#include "serialport.h"
#include "appsettings.h"
#include "gopro.h"
#include "gps.h"
#include <QDebug>
#include <QTime>
#include <QTimer>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QQmlContext>
#include <QQmlApplicationEngine>
#include <QFile>
#include <QFileInfo>
#include <QTextStream>
#include <QByteArrayMatcher>
#include <QProcess>
int ecu; //0=apex, 1=adaptronic;2= OBD; 3= Dicktator ECU
int logging; // 0 Logging off , 1 Logging to file
int connectclicked =0;
QByteArray checksumhex;
QByteArray recvchecksumhex;
Connect::Connect(QObject *parent) :
QObject(parent),
m_serialport(Q_NULLPTR),
m_dashBoard(Q_NULLPTR),
m_gopro(Q_NULLPTR),
m_gps(Q_NULLPTR),
m_adaptronicselect(Q_NULLPTR),
m_apexi(Q_NULLPTR),
m_nissanconsult(Q_NULLPTR),
m_OBD(Q_NULLPTR),
m_sensors(Q_NULLPTR),
m_haltechCANV2(Q_NULLPTR),
m_adaptronicCAN(Q_NULLPTR),
m_datalogger(Q_NULLPTR),
m_calculations(Q_NULLPTR)
{
getPorts();
m_dashBoard = new DashBoard(this);
m_appSettings = new AppSettings(this);
m_gopro = new GoPro(this);
m_gps = new GPS(m_dashBoard, this);
m_adaptronicselect= new AdaptronicSelect(m_dashBoard, this);
m_apexi= new Apexi(m_dashBoard, this);
m_nissanconsult = new Nissanconsult(m_dashBoard, this);
m_OBD = new OBD(m_dashBoard, this);
m_sensors = new Sensors(m_dashBoard, this);
m_haltechCANV2 = new HaltechCAN(m_dashBoard, this);
m_adaptronicCAN = new AdaptronicCAN(m_dashBoard, this);
m_datalogger = new datalogger(m_dashBoard, this);
m_calculations = new calculations(m_dashBoard, this);
QQmlApplicationEngine *engine = dynamic_cast<QQmlApplicationEngine*>( parent );
if (engine == Q_NULLPTR)
return;
engine->rootContext()->setContextProperty("Dashboard", m_dashBoard);
engine->rootContext()->setContextProperty("AppSettings", m_appSettings);
engine->rootContext()->setContextProperty("GoPro", m_gopro);
engine->rootContext()->setContextProperty("GPS", m_gps);
engine->rootContext()->setContextProperty("Nissanconsult",m_nissanconsult);
engine->rootContext()->setContextProperty("Sens", m_sensors);
engine->rootContext()->setContextProperty("Logger", m_datalogger);
}
Connect::~Connect()
{
}
void Connect::checkifraspberrypi()
{
QString path = "/sys/class/backlight/rpi_backlight/brightness";
if (QFileInfo::exists(path))
{
m_dashBoard->setscreen(true);
}
else
{
m_dashBoard->setscreen(false);
}
}
void Connect::readdashsetup()
{
qDebug()<<"c++ file read";
QString path = "UserDash.txt";// this is just for testing
QFile inputFile(path);
if (inputFile.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile);
while (!in.atEnd())
{
QString line = in.readLine();
QStringList list = line.split(QRegExp("\\,"));
m_dashBoard->setdashsetup(list);
qDebug()<< list;
}
inputFile.close();
}
}
void Connect::setSreenbrightness(const int &brightness)
{
//This works only on raspberry pi
QFile f("/sys/class/backlight/rpi_backlight/brightness");
//f.close();
f.open(QIODevice::WriteOnly | QIODevice::Truncate);
QTextStream out(&f);
out << brightness;
//qDebug() << brightness;
f.close();
}
void Connect::setUnits(const int &units)
{
switch (units)
{
case 0:
m_dashBoard->setunits("metric");
break;
case 1:
m_dashBoard->setunits("imperial");
break;
default:
break;
}
}
void Connect::setWeight(const int &weight)
{
m_dashBoard->setWeight(weight);
qDebug() << "weight" << m_dashBoard->Weight();
}
void Connect::getPorts()
{
QStringList PortList;
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
PortList.append(info.portName());
}
setPortsNames(PortList);
// Check available ports every 1000 ms
QTimer::singleShot(1000, this, SLOT(getPorts()));
}
//function for flushing all Connect buffers
void Connect::clear() const
{
// m_Connectport->clear();
}
//function to open Connect port
void Connect::openConnection(const QString &portName, const int &ecuSelect)
{
ecu = ecuSelect;
//Apexi
if (ecuSelect == 0)
{
m_apexi->openConnection(portName);
}
//Adaptronic
if (ecuSelect == 1)
{
m_adaptronicselect->openConnection(portName);
}
//OBD
if (ecuSelect == 2)
{
m_OBD->openConnection(portName);
}
//Nissan Consult
if (ecuSelect == 3)
{
m_nissanconsult->LiveReqMsg(1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
m_nissanconsult->openConnection(portName);
}
//Adaptronic ModularCAN protocol
if (ecuSelect == 5)
{
m_adaptronicCAN->openCAN();
}
//Haltech V2 CAN protocol
if (ecuSelect == 6)
{
m_haltechCANV2->openCAN();
}
}
void Connect::closeConnection()
{
//Apexi
if (ecu == 0)
{
m_apexi->closeConnection();
}
//Adaptronic Select
if (ecu == 1)
{
m_adaptronicselect->closeConnection();
}
//OBD
if (ecu == 2)
{
m_OBD->closeConnection();
}
//Nissan Consult
if (ecu == 3)
{
m_nissanconsult->closeConnection();
}
//Adaptronic ModularCAN protocol
if (ecu == 5)
{
m_adaptronicCAN->closeConnection();
}
//Haltech V2 CAN protocol
if (ecu == 6)
{
m_haltechCANV2->closeConnection();
}
}
void Connect::update()
{
m_dashBoard->setSerialStat("Update started");
QProcess *process = new QProcess(this);
connect(process , SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(updatefinished(int, QProcess::ExitStatus)));
process->start("/home/pi/updatePowerTune.sh");
process->waitForFinished(6000000); // 10 minutes time before timeout
}
void Connect::updatefinished(int exitCode, QProcess::ExitStatus exitStatus)
{
qDebug() << "code" <<exitCode;
qDebug() << "status" <<exitStatus;
QString fileName = "/home/pi/build/PowertuneQMLGui";
QFile file(fileName);
if(QFileInfo::exists(fileName))
{
m_dashBoard->setSerialStat("Update Successful");
file.close();
}
else
{
m_dashBoard->setSerialStat("Update Unsuccessful");
}
}
connect.h
#ifndef CONNECT_H
#define CONNECT_H
#include <QtSerialPort/QSerialPort>
#include <QObject>
#include <QModbusDataUnit>
#include <QTimer>
#include <QProcess>
#include "calculations.h"
class SerialPort;
class Sensors;
class DashBoard;
class AdaptronicCAN;
class AdaptronicSelect;
class Apexi;
class HaltechCAN;
class Nissanconsult;
class OBD;
class datalogger;
class calculations;
class AppSettings;
class GoPro;
class GPS;
class OBD;
class Connect : public QObject
{
Q_OBJECT
Q_PROPERTY(QStringList portsNames READ portsNames WRITE setPortsNames NOTIFY sig_portsNamesChanged)
public:
~Connect();
explicit Connect(QObject *parent = 0);
Q_INVOKABLE void checkifraspberrypi();
Q_INVOKABLE void readdashsetup();
Q_INVOKABLE void setSreenbrightness(const int &brightness);
Q_INVOKABLE void setUnits(const int &units);
Q_INVOKABLE void setWeight(const int &weight);
Q_INVOKABLE void clear() const;
Q_INVOKABLE void openConnection(const QString &portName, const int &ecuSelect);
Q_INVOKABLE void closeConnection();
Q_INVOKABLE void update();
public:
QStringList portsNames() const { return m_portsNames; }
private:
SerialPort *m_serialport;
DashBoard *m_dashBoard;
AppSettings *m_appSettings;
GoPro *m_gopro;
GPS *m_gps;
AdaptronicSelect *m_adaptronicselect;
Apexi *m_apexi;
Nissanconsult* m_nissanconsult;
OBD* m_OBD;
Sensors *m_sensors;
HaltechCAN *m_haltechCANV2;
AdaptronicCAN *m_adaptronicCAN;
datalogger *m_datalogger;
calculations *m_calculations;
QStringList m_portsNames;
QStringList *m_ecuList;
QThread* CALCThread;
QProcess process;
signals:
void sig_portsNamesChanged(QStringList portsNames);
public slots:
void updatefinished(int exitCode, QProcess::ExitStatus exitStatus);
void getPorts();
void setPortsNames(QStringList portsNames)
{
if (m_portsNames == portsNames)
return;
m_portsNames = portsNames;
emit sig_portsNamesChanged(portsNames);
}
};
#endif // CONNECT_H
dashbboard.cpp
#include <dashboard.h>
#include <QStringList>
#include <QDebug>
DashBoard::DashBoard(QObject *parent)
: QObject(parent)
{
}
void DashBoard::setdashsetup(const QStringList &dashsetup)
{
if (m_dashsetup == dashsetup)
return;
m_dashsetup = dashsetup;
emit dashsetupChanged(dashsetup);
}
//User Dashboard Stringlist
QStringList DashBoard::dashsetup() const { return m_dashsetup; }
dashboard.h
#ifndef DASHBOARD_H
#define DASHBOARD_H
#include <QStringList>
#include <QObject>
class DashBoard : public QObject
{
Q_OBJECT
//User Dashboard Stringlist dashsetup
Q_PROPERTY(QStringList dashsetup READ dashsetup WRITE setdashsetup NOTIFY dashsetupChanged)
public:
DashBoard(QObject *parent = 0);
//User Dashboard Stringlist
QStringList dashsetup() const;
signals:
QStringList m_dashsetup;
};
#endif // DASHBOARD_H
main.qml:
import QtQuick 2.8
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.1
import com.powertune 1.0
ApplicationWindow {
visible: true
width: 800
height: 480
minimumWidth: 800
minimumHeight: 480
title: qsTr("PowerTune ") + Dashboard.Platform + " Beta 24"
// visibility: "FullScreen"
color: "black"
Connections{
target: Dashboard
ondashsetupChanged: console.log("Dashboard has changed")
}
Item {
id: name
Component.onCompleted: Connect.checkifraspberrypi()
}
SwipeView {
id: view
currentIndex: 0
anchors.fill: parent
Loader {
id: firstPageLoader
source: ""
}
Loader {
id: secondPageLoader
source: ""
}
Loader {
id: thirdPageLoader
source: ""
}
Loader {
id: fourthPageLoader
source: ""
}
Item {
id:lastPage
SerialSettings{}
}
}
PageIndicator {
id: indicator
count: view.count
currentIndex: view.currentIndex
anchors.bottom: view.bottom
anchors.horizontalCenter: parent.horizontalCenter
}
}
The first letter of the property name is always capitalised in signal handlers:
onDashsetupChanged: console.log("Dashboard has changed")
Property Change Signal Handlers explains this:
A signal is automatically emitted when the value of a QML property changes. This type of signal is a property change signal and signal handlers for these signals are written in the form onChanged where is the name of the property, with the first letter capitalized.
I have some problems with qt + qml: Sometimes I get segmentation fault trying to clear QQmlengine. And even if program doesn't crashes it has memory leaks. (sorry for my english). I think so because the larger qml file (many nested classes) the larger application process even after QQmlengine was deleted. So my question is what am I doing wrong in the code below?
//main.cpp
#include "qmlwindow.h"
#include <QApplication>
int QMLwindow::someValue = 0;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);
QSharedPointer<QMLwindow> w0(new QMLwindow);
QSharedPointer<QMLwindow> w1(new QMLwindow);
QSharedPointer<QMLwindow> w2(new QMLwindow);
w0.data()->createWindow();
w0.data()->createWindow();
w1.data()->createWindow();
w2.data()->createWindow();
return a.exec();
}
//qmlwindow.h
#ifndef QMLWINDOW_H
#define QMLWINDOW_H
#include <QObject>
#include <QQmlComponent>
#include <QQuickWindow>
#include <QSharedPointer>
#include <QDebug>
#include <QQmlEngine>
#include <QQmlContext>
class QMLwindow : public QObject
{
Q_OBJECT
private:
QSharedPointer<QQmlEngine> engine;
QQmlComponent *component;
QObject *windowObj;
QQuickWindow *loginWindow;
QVariant count;
public:
static int someValue;
explicit QMLwindow(QObject *parent = 0);
~QMLwindow();
void createWindow();
signals:
public slots:
void deleteWindow(QQuickCloseEvent *event);
};
#endif // QMLWINDOW_H
//qmlwindow.cpp
#include "qmlwindow.h"
QMLwindow::QMLwindow(QObject *parent) : QObject(parent)
{
someValue++;
count = someValue;
qDebug() << "construction of QMLwindow " << count.toInt();
}
QMLwindow::~QMLwindow()
{
qDebug() << "destruction of QMLwindow " << count.toInt();
}
void QMLwindow::createWindow(){
if(engine.isNull()){
engine = QSharedPointer<QQmlEngine>(new QQmlEngine);
component = new QQmlComponent(engine.data());
component->loadUrl(QUrl(QStringLiteral("qrc:/SomeWindow.qml")));
Q_ASSERT(component->isReady());
windowObj = component->create();
loginWindow = qobject_cast<QQuickWindow *> (windowObj);
engine.data()->rootContext()->setContextProperty("someValue", count) ;
connect(loginWindow, SIGNAL(closing(QQuickCloseEvent*)), SLOT(deleteWindow(QQuickCloseEvent*)));
loginWindow->show();
}
else loginWindow->show();
}
void QMLwindow::deleteWindow(QQuickCloseEvent*event){
Q_UNUSED(event)
if(!engine.isNull()) {
qDebug() << "loginWindow destruction";
engine.clear();
}
this->deleteLater();
}
//SomeWindow.qml
import QtQuick 2.3
import QtQuick.Window 2.0
Window {
width: 200
height: 200
color: "white"
Text{
text: someValue
anchors.centerIn: parent
}
}