对于同一项目,有qml函数和c ++插槽的最佳方法,反之亦然

nee*_*eru 4 c++ qt qml qtquick2

我想做这样的事情

QML app:

  {
    signal qmlSignal
    function qmlFunction
  }
Run Code Online (Sandbox Code Playgroud)

c++ Hnadler:

  {
     c++ slot
     c++ signal
  }
Run Code Online (Sandbox Code Playgroud)

希望与同一个qml对象进行双向通信.我指的是http://qt-project.org/doc/qt-4.8/qtbinding.html

要从C++中更改qml中的值,我们可以做到

  QDeclarativeEngine engine;
  QDeclarativeComponent component(&engine, "MyItem.qml");
  QObject *object = component.create();

  QVariant returnedValue;
  QVariant msg = "Hello from C++";
  QMetaObject::invokeMethod(object, "myQmlFunction",
     Q_RETURN_ARG(QVariant, returnedValue),
     Q_ARG(QVariant, msg));

 qDebug() << "QML function returned:" << returnedValue.toString();
 delete object;
Run Code Online (Sandbox Code Playgroud)

可以用来调用qml函数.但是有了这个,我们就不能使用QT方法了

class MyClass : public QObject
{
   Q_OBJECT
  public slots:
   void cppSlot(const QString &msg) {
     qDebug() << "Called the C++ slot with message:" << msg;
 }
};

int main(int argc, char *argv[]) {
   QApplication app(argc, argv);

   QDeclarativeView view(QUrl::fromLocalFile("MyItem.qml"));
   QObject *item = view.rootObject();
   MyClass myClass;
   QObject::connect(item, SIGNAL(qmlSignal(QString)),
                  &myClass, SLOT(cppSlot(QString)));

   view.show();
   return app.exec();
 }
Run Code Online (Sandbox Code Playgroud)

这可以用于qmlsignal和c ++插槽.有没有一种方法可以在一个对象中完成?

lpa*_*app 7

===更新了问题===

你可以在QML中调用槽或Q_INVOKABLE方法来改变QML中的"C++属性".您需要将C++对象公开为上下文属性.你需要写下面这样的东西:

myclass.h

class MyClass : public QObject
{
    Q_OBJECT
    public:
        MyClass(QObject *parent) : QObject(parent) { ... }

    Q_INVOKABLE void myInvokable();

    public slots:
        void mySlot();

    ...
}
Run Code Online (Sandbox Code Playgroud)

main.cpp中

...

MyClass myClassObject;
QQuickView view;
view.rootContext()->setContextProperty("myClassContextProperty", &myClassObject;
view->setSource(QUrl::fromLocalFile("main.qml"));
view->show();

...
Run Code Online (Sandbox Code Playgroud)

main.qml

Button {

    ...

    // You can replace onClicked with your own custom signal

    onClicked: myClassContextProperty.myslot()

    // or

    onClicked: myClassContextProperty.myInvokable()

    ...
}
Run Code Online (Sandbox Code Playgroud)

===评论中的其他问题===

您将在C++中使用Q_PROPERTY,并在QML中将该属性绑定到您的属性,或者捕获名为"foo"的属性的onFooChanged信号处理程序.

myclass.h

class MyClass : public QObject
{
    Q_OBJECT
    Q_PROPERTY(foo READ foo NOTIFY fooChanged)
    public:
        MyClass(QObject *parent) : QObject(parent) { ... }

        int foo() const;        

    public signals:
        void fooChanged();

    public slots:
        void mySlot() { foo = 5; emit fooChanged(); };

    private:
        int foo;

    ...
}
Run Code Online (Sandbox Code Playgroud)

main.cpp中

...

MyClass myClassObject;
QQuickView view;
view.rootContext()->setContextProperty("myClassContextProperty", &myClassObject;
view->setSource(QUrl::fromLocalFile("main.qml"));
view->show();

...
Run Code Online (Sandbox Code Playgroud)

main.qml

...
// Bind foo to bar
property int bar: myClassContextProperty.foo
Run Code Online (Sandbox Code Playgroud)

===原始问题===

您似乎在试图询问是否可以同时在C++和QML中声明相同的内容,即QML中的某些部分,然后是QML中的其余部分.

我认为您需要使用Qt元类型系统注册(qmlRegisterMetaType等)您的C++类型,然后您可以将该类用作QML中的项目(可能与父级?)来实现您的期望.

这是进一步阅读的相关文件:

注册可实例化的对象类型

为方便起见,这里有一些内联代码:

message.h

class Message : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged)
    Q_PROPERTY(QDateTime creationDate READ creationDate WRITE setCreationDate NOTIFY creationDateChanged)
public:
    // ...
};

qmlRegisterType<Message>("com.mycompany.messaging", 1, 0, "Message");

...
Run Code Online (Sandbox Code Playgroud)

main.qml

import com.mycompany.messaging 1.0

Message {
    author: "Amelie"
    creationDate: new Date()
}
Run Code Online (Sandbox Code Playgroud)