[Qt-qml] The best way to use a QML button to start a new process?
Colin Kern
colin.kern at gmail.com
Tue Apr 13 18:42:02 CEST 2010
On Sat, Apr 10, 2010 at 12:17 PM, Peter Matuchniak
<pmatuchniak at imsco-us.com> wrote:
> Thanks Colin, but I already visited that link before and although it explains some of the pieces involved, I don't see a coherent picture of how these things fit together -- it lacks context and a step-by-step approach.
>
I guess I'll try writing a step-by-step approach.
1) C++ Classes
Any classes you want to have access to in QML need to be subclassed
from QObject. There are two ways to expose a method of a QObject to
QML. One way is to simply make it a public slot. The other way is to
use the Q_INVOKABLE macro, which should be put at the beginning of the
definition of the method like it's any other keyword. Example:
class A : public QObject
{
Q_OBJECT
public:
void foo(); //NOT available to QML
Q_INVOKABLE int bar(); //AVAILABLE to QML
public slots:
void foobar(); //AVAILABLE to QML
};
2) Adding objects to the QML environment
Now that you've written your class and made some of the methods
available to QML, you'll need to expose any instances of that object
you create to QML also. You can instantiate objects in C++ code and
then register them with the declarative script context (QML is a
QtScript engine behind the scenes) or you can instantiate the objects
directly in QML/Javascript.
2a. Creating objects in C++
If you used Qt Creator and created a QML Project, then you may not
have a C++ main function. Instead, Qt Creator is using an external
program to load and run your QML files. You will need to change your
project so that you have your own main function and are setting up the
QML environment yourself. In your main function (or in code
eventually called from your main function):
QDeclarativeEngine *engine = new QDeclarativeEngine;
QDeclarativeComponent component(engine, QUrl("myComponent.qml"));
QObject *window = component.create();
The QObject window will then become the Qt widget that displays/runs
your qml file. To create and expose a C++ object, your code would
become:
QDeclarativeEngine *engine = new QDeclarativeEngine;
QDeclarativeComponent component(engine, QUrl("myComponent.qml"));
QDeclarativeContext *context = new QDeclarativeContext(engine->rootContext());
context->setContextProperty("myObj", new Foo);
QObject *window = component.create(context);
You can probably store the QDeclarativeContext and add objects to it
after the creation of window, so you don't have to create every object
you're going to need during your program's setup (I'm not sure exactly
the details of that). If you're familiar with QtScript, this should
look pretty familiar. The QDeclarative* classes behave in much the
same way as the QScript* classes, since QML is itself a QtScript
environment.
2b. Creating objects in QML
This is something I'm not as familiar with. It probably works
similarly to creating C++ objects in QtScript, see
http://qt.nokia.com/doc/4.7-snapshot/scripting.html#making-a-qobject-based-class-new-able-from-a-script
(gmail will probably break the link when it inserts line breaks,
sorry)
3. Using C++ objects in QML
Once the C++ object instances are in QML's script context, you can
reference them like normal. Assuming the code from 2a, you could have
something like:
import Qt 4.6
Rectangle {
MouseArea {
onClicked: myObj.bar();
}
}
or you can call it in any .js file since 'myObj' is a global variable
in QML. There might be a way to scope it but I'm not familiar with
doing that.
Hope that helps. Chances are I've made some mistakes or said some
misleading things, hopefully someone will correct me.
Colin
More information about the Qt-qml
mailing list