I'm trying to make a very basic timetable app just to learn the basics of Qt. I've researched this quite a bit and cant seem to get an answer to my problem, I emit the signal when I change the value of my subject but the emitting signal does not update the GUI. It definitely is changing the value in the code but the QML GUI does not update it during run time.
I have a class called Day with the following Q_PROPERTY's:
Q_PROPERTY(Period *getPeriod READ getPeriod WRITE setPeriod NOTIFY periodChanged)
Q_PROPERTY(QString getDay READ getDay WRITE setDay NOTIFY dayChanged)
and a member to hold the periods
Period *m_period = new Period[10]; //Of type Period (my other class) which holds my subject string
I also have getters and setters for the days and periods(as seen in the Q_PROPERTY) and these two for setting/getting the subject:
Q_INVOKABLE QString getSubject(int t){
return m_period[t].getSub();
};
Q_INVOKABLE void setSubject(int t, QString subj){
m_period[t].setSub(subj);
emit periodChanged();
};
With the following signals:
void periodChanged();
void dayChanged();
I also have a class called Period with the following Q_PROPERTY:
Q_PROPERTY(QString getSub READ getSub WRITE setSub NOTIFY subChanged)
and a member to hold the subject names:
QString subject;
My Period class hold the functions called in day to actually change the QString subject:
QString getSub(){
return subject;
};
void setSub(QString sub){
subject = sub;
emit subChanged();
};
With the following signal:
void subChanged();
So surely when the subject gets changed using setSubject() in my QML, shouldn't it be emitting the periodChanged() and the subChanged() signals, which should update the GUI? I thought it would but it doesn't seem to be working.
For reference, this is basically how I implemented it in QML:
Label { text: monday.getSubject(2) } //How I display the Subject, the parameter being the period number
Button{
text: "Enter"
onClicked:{
monday.setSubject(2, "RANDOM_TEXT") //How I set the subject at run time, with the first argument being the period number and second the text I want to change it to
}
Here are the main and class files:
main.cpp
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
qmlRegisterType<Day>("Timetable", 1,0, "Day");
qmlRegisterType<Period>("Timetable", 1,0, "Period");
QQmlApplicationEngine engine;
Day monday;
engine.rootContext()->setContextProperty("monday", &monday);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
QQmlComponent component(&engine, QUrl::fromLocalFile("main.qml"));
component.create();
return app.exec();
}
Day.h
class Day : public QObject
{
Q_OBJECT
Q_PROPERTY(Period *getPeriod READ getPeriod WRITE setPeriod NOTIFY periodChanged)
private:
Period *m_period = new Period[10];
public:
Day(QObject *parent = 0);
~Day();
Period* getPeriod();
Q_INVOKABLE void setPeriod(Period *p);
Q_INVOKABLE QString getSubject(int t){
return m_period[t].getSub();
};
Q_INVOKABLE void setSubject(int t, QString subj){
m_period[t].setSub(subj);
emit periodChanged();
};
signals:
void periodChanged();
};
Period.h
class Period: public QObject
{
Q_OBJECT
Q_PROPERTY(QString getSub READ getSub WRITE setSub NOTIFY subChanged)
private:
QString subject;
public:
Period(QObject *parent = 0);
~Period();
QString getSub(){
return subject;
};
void setSub(QString sub){
subject = sub;
emit subChanged();
};
signals:
void subChanged();
};
main.qml
ApplicationWindow {
id: mainWindow
visible: true
title: "Timetable App"
property int margin: 11
width: mainLayout.implicitWidth + 2 * margin
height: mainLayout.implicitHeight + 2 * margin
minimumWidth: 800
minimumHeight: 600
ColumnLayout {
id: mainLayout
anchors.fill: parent
anchors.margins: margin
GroupBox{
id: timetable
title: "Timetable"
Layout.fillWidth: true
Layout.fillHeight: true
GridLayout {
id: gridLayout
rows: 11
flow: GridLayout.TopToBottom
anchors.fill: parent
Layout.fillWidth: true
Layout.fillHeight: true
Label { }
Label { text: "8:00" }
Label { text: ...} // Added Labels for times from 8:00 to 17:00
Label { text: "Monday" }
Label { text: monday.getSubject(0) }
Label { text: monday.getSubject(1) }
Label { text: ...} // Added Labels to display subjects for monday at different times, also did the same for the rest of the week
}
}
RowLayout{
Button{
text: "Enter"
onClicked:{
monday.setSubject(1, "RANDOM_TEXT") // Set the second period of monday to "RANDOM_TEXT"
console.log(monday.getSubject(1)) // To check if actually set
}
}
}
}
}
Your problem is that you are retrieving values via method calls in QML, not via property bindings.
A QML code like this should update
text: monday.getPeriod.getSub
Obviously calling properties "getSomething" is a bit weird.
Now, your m_period
suggests that a single Day
object will have more than one Period
, which would suggest that you might want a list property instead of a single Period
object. Something like
Q_PROPERTY(QList<Period*> periods READ getPeriods NOTIFY periodsChanged);
Using that from QML a bit like this
text: monday.periods[0].getSub
Or even with eg a Repeater
Label { text: "Monday" }
Repeater {
model: monday.periods
Label {
text: modelData.getSub
}
}
Not related to your update problem but also important to consider: NOTIFY
signals trigger binding updates, so you don't want to emit them unnecessarily. Ie setters that emit those should first check if the new value is actually different than the old value and only emit if they are.
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.