1. 程式人生 > >c++中的訊號與QML中的函式繫結(連結)起來 以及qml與c++互動重要筆記

c++中的訊號與QML中的函式繫結(連結)起來 以及qml與c++互動重要筆記

signals:

Q_INVOKABLE void buttonLeft();

    Q_INVOKABLE void buttonRight();
    Q_INVOKABLE void buttonShort();

    Q_INVOKABLE void buttonLong();

void CarStatus::buttonRightDeal(bool v)
{
   ...
        emit buttonRight();

    }

qml中

Component.onCompleted: {
        CarStatus.buttonLeft.connect(buttonLeft);
        CarStatus.buttonRight.connect(buttonRight);
        CarStatus.buttonShort.connect(buttonShort);
        CarStatus.buttonLong.connect(buttonLong);
    }

轉載部分:

QQuickView是顯示QtQuick使用者介面的視窗。 它的基類是QQuickWindow,通過指定qml原始檔的路徑自動載入和顯示QML場景。另一種方法是使用QQuickWindow和QQmlComponent配合載入QML。
QQuickView *view = new QQuickView;
view->setSource(QUrl::fromLocalFile("myqmlfile.qml"));
view->show();
通過元物件系統的互動, QML引擎可以直接訪問QObject類的所有功能。
Properties
Methods (必須是public slots或者標記為Q_INVOKABLE)


Signals
如果要把QObject類作為資料型別使用時,必須註冊為QML型別,例如:把該類或該類的列舉作為訊號引數或方法引數和返回值以及宣告為屬性

暴露屬性到QML
1.使用巨集Q_PROPERTY()可以為任何QObject類指定屬性。屬性是類的資料成員,有一個關聯的讀函式,一個關聯的寫函式和值變化訊號。QML通過屬性和它的關聯函式訪問QObject類中的資料成員
class Message : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged)

public:
    void setAuthor(const QString &a) {
        if (a != m_author) {
            m_author = a;
            emit authorChanged();
        }
    }
    QString author() const {
        return m_author;
    }
signals:
    void authorChanged();
private:
    QString m_author;
};

2.建立QML執行時,把這個類的一個物件設定為QML引擎上下文的屬性:
 int main(int argc, char *argv[]) {
     QCoreApplication app(argc, argv);
     QQmlEngine engine;
     Message msg;
     engine.rootContext()->setContextProperty("msg", &msg);
     QQmlComponent component(&engine, QUrl::fromLocalFile("MyItem.qml"));
     component.create();
     return app.exec();
 }

3.在QML程式碼中讀寫這個物件的屬性
// MyItem.qml
import QtQuick 2.0
Text {
    width: 100; height: 100
    text: msg.author    // invokes Message::author() to get this value
    Component.onCompleted: {
        msg.author = "Jonah"  // invokes Message::setAuthor()
    }
}
為了與最大化地與QML整合,任何可寫的屬性都要有一個與其關聯的NOTIFY訊號。屬性值發生改變時,訊號傳送。這允許該屬性可以用於屬性繫結。

暴露方法到QML
1.通過以下兩種方式把QObject類任何方法暴露到QML程式碼。
    使用巨集Q_INVOKABLE()標記公共方法
    把方法宣告為公共槽函式 public slots
 class MessageBoard : public QObject
 {
     Q_OBJECT
 public:
     Q_INVOKABLE bool postMessage(const QString &msg) {
         qDebug() << "Called the C++ method with" << msg;
         return true;
     }
 public slots:
     void refresh() {
         qDebug() << "Called the C++ slot";
     }
 };

2.建立QML執行時,把這個類的一個物件設定為QML引擎上下文的屬性:
 int main(int argc, char *argv[]) {
     QGuiApplication app(argc, argv);
     MessageBoard msgBoard;
     QQuickView view;
     view.engine()->rootContext()->setContextProperty("msgBoard", &msgBoard);
     view.setSource(QUrl::fromLocalFile("MyItem.qml"));
     view.show();
     return app.exec();
 }

3.在QML程式碼中讀寫這個物件的方法:
// MyItem.qml
import QtQuick 2.0
Item {
    width: 100; height: 100
    MouseArea {
        anchors.fill: parent
        onClicked: {
            var result = msgBoard.postMessage("Hello from QML")
            console.log("Result of postMessage():", result)
            msgBoard.refresh();
        }
    }
}
如果C++方法有QObject型別的引數時,在QML程式碼使用物件ID或var值來完成引數傳遞。

暴露訊號到QML
1.QML引擎會為QObject型別的任何訊號自動建立訊號處理器。on<Signal>是訊號處理器的名字,其中Signal是訊號的名字。訊號處理器通過訊號的引數名字來處理傳遞過來的引數。
 class MessageBoard : public QObject
 {
     Q_OBJECT
 public:
    // ...
 signals:
    void newMessagePosted(const QString &subject);
 };

2.把MessageBoard註冊為QML的型別後才能用於宣告MessageBoard物件,使用訊號處理器onNewMessagePosted來處理newMessagePosted()的訊號。
MessageBoard {
    onNewMessagePosted: console.log("New message received:", subject)
}
訊號引數的型別與方法引數和屬性的型別一樣,都必須是QML引擎支援的型別。

如果不想把C++物件註冊為QML型別,還可以使用connection物件響應C++訊號。
Connections {
    target: MessageBoard 
onNewMessagePosted: console.log("New message received:", subject)
}