Been having some fun this week trying to add support for data bindings to Qt Script, and now I have something that seems to work. This code shows the basic usage:
QScriptEngine engine;
QPushButton button;
QScriptValue scriptButton = engine.newQObject(&button);
engine.evaluate("x = 'foo'");
scriptButton.setProperty("text", "x", QScriptValue::DataBinding);
This will cause the button’s text property to be updated whenever the script variable x changes, either from C++ (QScriptValue::setProperty()) or from
script. QObject properties can be part of the binding expression as well, as long as the NOTIFY attribute is specified in the Q_PROPERTY definition. Qt Script will discover that the property has a signal associated with it and use it to track changes. Qt’s classes already use NOTIFY for some properties (e.g. QLabel::text).
Below is a small example. The text property of a label is bound to the text property of a lineedit and the script variable verb; the final value is made by concatenating the lineedit’s text, the verb and a string literal.
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget win;
QVBoxLayout *vbox = new QVBoxLayout(&win);
QLineEdit *lineEdit = new QLineEdit();
QLabel *label = new QLabel();
label->setStyleSheet("font-size: 24px");
vbox->addWidget(lineEdit);
vbox->addWidget(label);
QScriptEngine engine;
QScriptEngineDebugger debugger;
debugger.attachTo(&engine);
vbox->addWidget(debugger.widget(QScriptEngineDebugger::ConsoleWidget));
QScriptValue scriptLineEdit = engine.newQObject(lineEdit);
engine.globalObject().setProperty("lineEdit", scriptLineEdit);
QScriptValue scriptLabel = engine.newQObject(label);
engine.globalObject().setProperty("label", scriptLabel);
engine.evaluate("verb = 'smack'");
scriptLabel.setProperty("text", "lineEdit.text + ' ' + verb + 's you!'", QScriptValue::DataBinding);
win.show();
return app.exec();
}
The result, after typing something into the lineedit and assigning something to verb:
I’ve also added an extension to QScriptClass that enables you to send property change notifications for custom (non-QObject-based) script objects, i.e. you can use your own notify mechanism.
As I said, this isn’t in Qt yet, it’s just an experiment, but it’s looking pretty interesting.
10 Responses to “Data Bindings”
Thats pretty mind-blowing. Is there some language construct your emulating here?
I see how its useful, I’m just not sure where you’d get the idea to do something like this. ![]()
Makes me think of https://beansbinding.dev.java.net/
You might find inspiration there ![]()
sounds usefull but i would like to have the same in c++.
Connecting properties directly to widgets without the need to write for each small dialog x set/get widget functions
JarJar, where do you think these properties come from? They’re defined by set/getters.
In the example Kent could’ve done lineEdit.text = “love” instead and it would’ve worked. I guess its a small example. But I don’t get the point…
Ah I guess not, I misread. I’ll go back to seeing how it could be useful but wondering why you’d do it this way. ![]()
JarJarThomas: Yep, you will be able to that, similar to how there’s qScriptConnect() in C++. There will be a function like this:
QScriptEngine::bindProperty(QObject* object, QString name, QString expression)
Ian: I didn’t get the idea. There’s JavaFX and WPF, for example.
Can you tell me more about the NOTIFY-keyword of Q_PROPERTY? It looks like something I wanted in Qt for years and that I finally submitted as feature request: http://trolltech.com/developer/task-tracker/index_html?method=entry&id=217531
I dont see any documentation for it neither in the documentation of Q_OBJECT nor QMetaProperty. If it is a new feature that is about to be added in Qt 4.5, please make sure that you can query for the signal in QMetaProperty. Then you could add two text labels to a form, bind them to x and y of the form and show them the position of the form while moving in preview mode. Very cool.
Axel: Yes, this is what you’re looking for: http://doc.trolltech.com/main-snapshot/qmetaproperty.html#notifySignal
Unfortunately the docs haven’t been updated yet.
If you use NOTIFY in the property definition (e.g. “NOTIFY textChanged”), QMetaProperty::notifySignal() will return a QMetaMethod that describes the notify signal (i.e. so you can connect to it).
How will the change of dynamic properties be tracked? Will there be a signal for this? Will the Qt api be updated to have change signals for every property?