Chapter 4: Calling C++ Interaction in QML

 

1. Call C++ interactive method in QML

Qt integrates the QML engine and the Qt meta-object system, making QML easy to be extended from C++. Under certain conditions, QML can access members of QObject-derived classes, such as signals, slot functions, enumeration types, attributes, and members Functions etc.

 

QML access to C++ needs to extend the C++ class to qml, there are two methods:

1. Register the C++ class to qml in the Qt meta-object system

2. Expose the object or data to QML

related functions:

setContextProperty()//将对象或数据暴露给 QML
qmlRegisterType()//注册C++类到qml中
qmlRegisterSingletonType()//注册C++单例到qml中

 

Two conditions must be met to implement the properties and methods of C++ classes that can be accessed by QML:

1. Derived from the QObject class or a subclass of the QObject class

2. Use the Q_OBJECT macro

 

Access properties and methods:

1. Signals and slots can be directly accessed

2. Enumeration types use the Q_ENUMS() macro

3. Use Q_PROPERTY() macro for properties

4. The method uses the Q_INVOKABLE() macro

 

2. Q_PROPERTY macro

effect:

It is used to define the attributes that can be accessed through the meta-object system. The attributes defined by it can be accessed and modified in QML, and can also emit specific signals when the attributes change. This macro is unique to qt and must be inherited from the QObject class.

Writing method:

Q_PROPERTY(type name   # 属性
   READ getFunction     # 读取属性值,必须返回属性的类型的值或指针或引用
   [WRITE setFunction]   # 设置属性值,返回空并且至少具有一个参数
   [RESET resetFunction]     # 设置属性的值到默认值
   [NOTIFY notifySignal]     # 属性的值发生改变时发出信号
   [DESIGNABLE bool]        # 此属性是否在界面设计器的属性编辑器中出现
   [SCRIPTABLE bool]        # 属性是否可以被一个脚本引擎操作
   [STORED bool]            # 属性是否被认为是独立存在还是依赖于其它的值而存在
   [USER bool]              # 属性是否被设计为面向用户的或用户可修改的类属性
   [CONSTANT]               # 属性的值是不变的
   [FINAL])                 # 属性不能被派生类所重写

Signal naming:

Name the NOTIFY signal in the form of <property>Changed, where <property> is the name of the property. The associated property change signal handler generated by the QML engine will always take the form of on<Property>Changed, without having to care about the name of the related C++ signal, so it is recommended that the signal name follow this convention to avoid any confusion.

Example:

Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(QColor barColor READ getBarColor WRITE setBarColor)

 

3. Q_INVOKABLE macro

Role: The modified member function can be evoked by the meta-object system

QML can access the functions of the QObject-derived class, but the function needs to meet one of the following conditions:

1. Public functions marked with the Q_INVOKABLE() macro

2. Public slot function

Example:

Q_INVOKABLE void qDebug_Info(int type, QString strInfo);

 

qmlRegisterType

Function: A tool that connects C++ and QML by calling classes implemented in C++ in QML

Writing method:

int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
int qmlRegisterType(const QUrl &url, const char *uri, int versionMajor, int versionMinor, const char *qmlName)

Example:

main.cpp

#include <QtQml>
qmlRegisterType<Boy>("People", 1,0, "Boy");
qmlRegisterType<Girl>("People", 1,0, "Girl");

xxx.qml

import People 1.0
Boy{
    id:boy
    ...
}
Girl{
    id:girl
    ...
}

 

4、setContextProperty

Role: Expose objects or data to QML, generally the default is a global singleton

Example: Using C++ logging module in QML

qmllog4qml.h

#include <QObject>
class QmlLog4Qml : public QObject
{
    Q_OBJECT
public:
    QmlLog4Qml();
    Q_INVOKABLE void qDebug_Info(int type, QString strInfo);
};

qmllog4qml.h.cpp

#include "qmllog4qml.h"
#include <QMutex>
#include <QFile>
#include <QDateTime>
#include <QTextStream>
void outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    static QMutex mutex;
    mutex.lock();
    QString text;
    switch(type)
    {
    case QtDebugMsg:
        text = QString("Debug:");
        break;
    case QtWarningMsg:
        text = QString("Warning:");
        break;
    case QtCriticalMsg:
        text = QString("Critical:");
        break;
    case QtFatalMsg:
        text = QString("Fatal:");
    }
    QString message = "";
    if (context.file != nullptr)
    {
        QString context_info = QString("File:(%1) Line:(%2)").arg(QString(context.file)).arg(context.line);
        QString current_date_time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");
        QString current_date = QString("(%1)").arg(current_date_time);
        message = QString("%1 %2 %3 %4").arg(current_date).arg(text).arg(context_info).arg(msg);
    }
    else
    {
        message = msg;
    }
    QFile file("log.txt");
    file.open(QIODevice::WriteOnly | QIODevice::Append);
    QTextStream text_stream(&file);
    text_stream << message << "\r\n";
    file.flush();
    file.close();
    mutex.unlock();
}
QmlLog4Qml::QmlLog4Qml()
{
    qInstallMessageHandler(outputMessage);
}

void QmlLog4Qml::qDebug_Info(int type, QString strInfo)
{
    QMessageLogContext context;
    context.file = nullptr;
    outputMessage((QtMsgType)type, context, strInfo);
}

 

main.cpp

Set the context property: setContextProperty() exports the property and it can be used in QML

#include "qmllog4qml.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
    QmlLog4Qml log4Qml;
    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("log4Qml", &log4Qml);
    engine.load(QUrl(QLatin1String("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;
    return app.exec();
}

QML: No import statement is required, log4Qml.qDebug_Info() can be called directly

...
Page1Form {
    Keys.enabled: true
    Keys.onEscapePressed: {
        Qt.quit()
    }
    searchbutton.onClicked: {
        log4Qml.qDebug_Info(0, "Qml写日志");   //调用C++接口
        console.log("查找内容:" + searchTextField.text);
    }
    ...
}

 

Guess you like

Origin blog.csdn.net/qq_40602000/article/details/109277170