Qt Quick基础用法+基本知识

本文介绍了QtQuick的基础知识,包括QtWidgets与QML/QtQuick的对比,QML的定义和用途,以及QtQuick1.x与2.x的区别。重点讲解了信号与槽的概念和使用,以及QML与C++的混合编程,包括QML如何访问C++类、C++如何设置QML上下文属性以及如何访问QML的属性和函数。文章还提到了QML与C++混合编程的原理和方法,强调了QML在UI设计中的便捷性和C++在处理复杂逻辑的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 简介

  • Qt 是一个跨平台的, 基于C++ 和 QML进行GUI开发的工具。

1.1 Qt Widgets 与 QML/Qt Quick

  • Qt 4.7 发布时,引入了 QML,用于移动开发,其全面支持触摸操作、流畅的动画效果等。但在 Qt 5 中,QML 已经不再局限于移动开发,也可用于开发传统的桌面程序。
    • 相比之下,Qt Widgets 更“老”、更成熟,而 QML/Qt Quick 则更“新”、更“现代”。
    • 无论如何,Qt Widgets 和 QML/Qt Quick 都可以在多个平台上使用(Windows、Linux、OS X等)
  • 对于传统的桌面程序来说,优先考虑使用 Qt Widgets,若要开发更“现代”的 UI 与高级应用,建议使用 Qt5.x + QML 2.x + QtQuick 2.x。
  • 对于移动端开发来说,建议使用 QML,协同 JavaScript,简单快捷、渲染效果更佳、界面更炫酷。不建议使用 Qt Widgets,其显示效果、适应性都不好。

2. QML与QtQuick

  • QML 是一种用户界面规范和标记语言,允许开发人员和设计师创建高性能、流畅的动画和视觉吸引人的应用程序。
    • 用户界面规范:QML 提供了一种高度可读、声明性、类似 JSON 的语法,支持与动态属性绑定相结合的命令式 JavaScript 表达式。
    • 标记语言:像 C++ 一样,QML 是一种语言,文件格式以 .qml 结尾。
  • Qt Quick 是 QML 类型和功能的标准库,包括视觉类型、交互式类型、动画、模型和视图、粒子效果和着色效果。
  • Qt Quick 使用 QML 作为声明语言,来设计以用户界面为中心的应用程序。
  • QML 包含大量使用手机移动设备的功能模块,比如基本部件(QtQuick 模块)、GPS 定位、渲染特效、蓝牙、NFC、WebkKit 等等。

2.1 QtQuick 1.x VS QtQuick 2.x

  • 全新的 Qt 版本
    • QtQuick 1.x 基于 Qt4.x。
    • QtQuick 2.x 随 Qt5.0 一起引入。
  • 全新的绘图系统
    • QtQuick 1.x 使用 QGraphicsView/QPainter API 来绘制场景。
    • QtQuick 2.x 基于 Scene Graph,一个 OpenGL(ES)2.0 抽象层,对绘图进行了高度优化,效率更高。
  • 全新的 QML 引擎
    • Qt 4.x 中,QML 引擎基于JSC(JavaScriptCore - Webkit 的 JS 引擎)。
    • Qt 5.0 中引入 V8(Google 的开源高性能 JavaScript 引擎,用 C++ 编写,用于 Chromium、Node.js 和多个其他嵌入应用程序)。
    • Qt 5.2 中引入了 V4 JS 引擎,针对 QML 用例进行了优化,并且可以选择关闭 JIT(Just-In-Time)编译,以符合 iOS 和 WinRT 平台的限制。个头更小、反应更快、扩展性也非常好。
    • 从 Qt 5.5 开始,加入了一个新模块 QtQuick3D,它提供使用 QML 语言创建 3D 应用程序/游戏的能力,其使用的是一个被命名为 FrameGraph 的新引擎,而非 Scene Graph(因为太 2D/2.4D)。
  • 模块、属性和方法、类型和 API、C++ 代码(QtDeclarative 被移除了,替代的它是Qt QML 和 Qt Quick 模块)、QML 插件的更改。

3. 信号(Signal )与槽(Slot)

  • 信号与槽(Signal & Slot)是 Qt 编程的基础,也是 Qt 的一大创新。因为有了信号与槽的编程机制,在 Qt 中处理界面各个组件的交互操作时变得更加直观和简单。

  • 槽(Slot):就是对信号响应的函数。

    • 槽就是一个函数,与一般的C++函数是一样的,可以定义在类的任何部分(public、private 或 protected),可以具有任何参数,也可以被直接调用。槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。
  • 信号(Signal):就是对控件的点击事件或定时事件

    • 就是在特定情况下被发射的事件,例如PushButton 最常见的信号就是鼠标单击时发射的 clicked() 信号,一个 ComboBox 最常见的信号是选择的列表项变化时发射的 CurrentIndexChanged() 信号。
  • 信号与槽关联是用 QObject::connect() 静态函数实现的,其基本格式是:

    • QObject::connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));
      • connect(ui->rBtnBlue,SIGNAL(clicked()),this,SLOT(setTextFontColor()));
      • connect(spinNum, SIGNAL(valueChanged(int)), this, SLOT(addFun(int));
    • 一个信号可以连接多个槽
    • 当信号和槽函数带有参数时,在 connect()函数里,要写明参数的类型,但可以不写参数名称。
    • 多个信号可以连接同一个槽
    • 一个信号可以连接另外一个信号,例如:connect(spinNum, SIGNAL(valueChanged(int)), this, SIGNAL (refreshInfo(int));
    • 严格的情况下,信号与槽的参数个数和类型需要一致,至少信号的参数不能少于槽的参数。如果不匹配,会出现编译错误或运行错误。
    • 在使用信号与槽的类中,必须在类的定义中加入宏 Q_OBJECT。
    • 当一个信号被发射时,与其关联的槽函数通常被立即执行,就像正常调用一个函数一样。只有当信号关联的所有槽函数执行完毕后,才会执行发射信号处后面的代码。
    • 信号与槽机制是 Qt GUI 编程的基础,使用信号与槽机制可以比较容易地将信号与响应代码关联起来。
  • 在Qt c++中通过emit来发射信号,而在QML中直接将声明的信号当做函数来调用就可以触发了。

  • 事件与信号:只要记住事件比信号更底层就可以了。事件由操作系统发出,信号由Qt的对象发出

  • QML兼具了UI界面文件和QtScript的特点,非常方便的将界面设计和与C++交互融化在了一起,这是Qt Quick最重要的特性,可以让我们以最便捷的方式去开发应用。

  • 在QtWidgets中,信号与槽的连接方式使用的是QObject::connect()。相应的,在QtQuick中,signal对象也有一个connect()方法,用于将信号连接到一个或多个方法/信号。当信号连接到方法时,无论信号何时发出,该方法都将被自动调用。
    有了这种机制,可以通过方法来接收信号,而无需使用信号处理器。也可以通过disconnect()来取消连接。

4. QML与C++混合编程

  • Qt Quick能够使我们的界面生成非常绚丽的效果,但是,它本身也是有局限性的,对于一些业务逻辑和复杂算法,比如低阶的网络编程如 QTCPSocket ,多线程,又如 XML 文档处理类库 QXmlStreamReader / QXmlStreamWriter 等等,在 QML 中要么不可用,要么用起来不方便。所以呢,我们基于这种原因来混合编程。

4.1 原理和方法

  • 简单来说,混合编程就是通过QML高效便捷的构建UI界面,而使用C ++来实现业务逻辑和复杂算法。
  • Qt集成了QML引擎和Qt元对象系统,使得QML很容易从C ++中得到扩展,在一定的条件下,QML就可以访问QObject派生类的成员,例如:
    • 信号 (signals)
    • 槽函数 (slots)
    • 枚举类型 (Q_ENUMS)
    • 属性 (Q_PROPERTY)
    • 成员函数 (Q_INVOKABLE )
  • 实例代码如下
class Mixing : public QObject
{
    Q_OBJECT
    Q_ENUMS(BALL_COLOR) // 定义可被 QML访问的枚举类型
    // 定义可被QML访问的属性number
    Q_PROPERTY(unsigned int number READ getNumber WRITE setNumber NOTIFY Numberchanged) 
public:
    explicit Mixing(QObject *parent = nullptr);
    enum BALL_COLOR{
        BALL_COLOR_YELLOW,
        BALL_COLOR_BLUE,
        BALL_COLOR_GREEN,
    };
    unsigned int getNumber() const;
    void setNumber(const unsigned int &Number);
    Q_INVOKABLE void stop(); // 定义可被QML调用的成员函数
signals: // 定义可被QML调用的信号
    void colorChanged(const QColor & color);
    void Numberchanged();
public slots: // 定义可被QML调用的槽函数
    void start();
private:
    unsigned int m_Number;
}
  • 要想在QML中访问C++对象,必然要找到一种方法在两者之间建立联系,而Qt中提供了两种在 QML 环境中使用C ++对象的方式:
    • 在C ++中实现一个类,注册到QML环境中,QML环境中使用该类型创建对象
    • 在C ++中构造一个对象,将这个对象设置为QML的上下文属性,在QML环境中直接使用该属性
    • 两种方式之间的区别是第一种可以使C ++类在QML中作为一个数据类型,例如函数参数类型或属性类型,也可以使用其枚举类型、单例等,功能更强大。

4.2 QML访问C++ 类 (QML=>C++)

  • C++类要想被QML访问,首先必须满足两个条件:一是派生自QObject类或QObject类的子类,二是使用Q_OBJECT宏。
  • QObject类是所有Qt对象的基类,作为Qt对象模型的核心,提供了信号与槽机制等很多重要特性。
  • Q_OBJECT宏必须在private区(C++默认为private)声明,用来声明信号与槽,使用Qt元对象系统提供的内容,位置一般在语句块首行。

4.2.1 信号和槽

  • 可以把 C++ 对象的信号连接到 QML 中定义的方法上,也可以把 QML 对象的信号连接到 C++ 对象的槽上,还可以直接调用 C++ 对象的槽或信号
  • 槽必须被声明为public或protected,而且信号在 C++ 中使用时要用到emit关键字,但是在Qml中就是个普通的函数
void Mixing::start()
{
    qDebug() << "start";
    emit colorChanged(Qt::blue); // 传递了一个颜色到QML中
}

4.2.2 把类注册到QML中

  • 注册函数原型
template<typename T>
int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
  • 参数说明:
    • 模板参数typename ,就是要实现的 C++ 类的类名。
    • uri:指定一个唯一的包名,类似Java 中的那种,一是用来避免名字冲突,二是可以把多个相关类聚合到一个包中方便引用。比如我们常写这个语句 “import QtQuick.Controls 2.3” ,其中的 “QtQuick.Controls” 就是包名 uri ,而2.3则是版本,是versionMajor和versionMinor的组合。
    • qmlName:是在QML中可以使用的类名
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include "mixing.h"
int main(int argc, char *argv[]) {
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
    qmlRegisterType<Mixing>("test.Mixing", 1, 0, "Mixing");
    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;
    return app.exec();
}
  • 上述示例代码把C++ Mixing类注册成为QML类型Mixing,主版本是1,次版本是0,包名是test.Mixing。注意:注册动作一定要放在 QML 上下文创建之前,否则的话,注册是没有用的。
  • 在QML中导入Mixing类并使用它
import QtQuick 2.9
import QtQuick.Window 2.2
import test.Mixing 1.0
Window {
    id:root
    visible: true
    width: 640
    height: 480
    title: qsTr("mixing")
    MouseArea{
        anchors.fill: parent
        onClicked: {
            mixing.start()
        }
    }
    Mixing{  // 创建Mixing对象,并实现信号colorChanged的槽函数
        id: mixing
        onColorChanged: {
            root.color = color
        }
    }
}

4.2.3 C++ 类的属性和成员函数

  • C++中定义可被QML调用的成员函数(Q_INVOKABLE):
    • 在定义一个类的成员函数时使用Q_INVOKABLE宏来修饰,但是注意的是在QML中访问的前提是public或protected成员函数,而且这个宏必须放在返回函数前面。
  • C++中定义 可被QML访问的属性(Q_PROPERTY ):
    • 定义属性则需要使用Q_PROPERTY 宏,通过它定义的属性,可以在 QML 中访问、修改,也可以在属性变化时发射特定的信号。要想使用 Q_PROPERTY 宏,定义的类必须是QObject的后裔,必须在类首使用Q_OBJECT宏。
class Mixing : public QObject
{
    Q_OBJECT
    Q_ENUMS(BALL_COLOR)
    Q_PROPERTY(unsigned int number READ getNumber WRITE setNumber NOTIFY Numberchanged)
public:
    explicit Mixing(QObject *parent = nullptr);
    enum BALL_COLOR{
        BALL_COLOR_YELLOW,
        BALL_COLOR_BLUE,
        BALL_COLOR_GREEN,
    };
    unsigned int getNumber() const;
    void setNumber(const unsigned int &Number);
    Q_INVOKABLE void stop();
signals:
    void colorChanged(const QColor & color);
    void Numberchanged();
public slots:
    void start(BALL_COLOR ballColor);
private:
    unsigned int m_Number;
}    
  • 通过Q_INVOKABLE修饰了stop函数。通过Q_PROPERTY修饰了名为number的属性,number通过Number函数读得数据,通过setNumber函数写入数据,触发信号是Numberchanged函数。
  • 成员函数和属性的实现
unsigned int Mixing::getNumber() const{
    return m_Number;
}

void Mixing::setNumber(const unsigned int &number){
    if(number != m_Number)    {
        m_Number = number;
        emit Numberchanged();
    }
}
void Mixing::stop(){
    qDebug() << "颜色改变啦!!!";
}

4.2.4 QML调用C++类的成员函数和属性

MouseArea{
    anchors.fill: parent
    acceptedButtons:Qt.LeftButton | Qt.RightButton;
    onClicked: {
        if(mouse.button === Qt.LeftButton)
        {
            mixing.start(Mixing.BALL_COLOR_BLUE)
        }else if(mouse.button === Qt.RightButton){
            mixing.start(Mixing.BALL_COLOR_GREEN)
        }
    }
    onDoubleClicked: {
        mixing.start(Mixing.BALL_COLOR_YELLOW)
        mixing.number = 10;
    }
}
Mixing{
    id: mixing
    onColorChanged: {
        root.color = color
        mixing.stop(color)
    }
    Component.onCompleted:
    {
        console.log("default ball number is", number)
    }
    onNumberChanged:
    {
        console.log("new ball number is", number) 
    }
}

4.3 QML上下文属性设置

  • 目标:直接嵌入一些 C++ 数据给QML使用,需要使用QQmlContext类
  • QQmlContext:
    • 定义了QML引擎内的上下文,上下文允许将数据暴露给由QML引擎实例化的QML组件
    • 每个QQmlContext包含一组属性,允许以名称将数据显式地绑定到上下文
    • 通过调用QQmlContext::setContextProperty()来定义和更新上下文属性
// 简单的上下文属性,对应的值为QVariant类型
void QQmlContext::setContextProperty(const QString &name, const QVariant &value)

// 相对来说稍微复杂一些,QObject*对象类型。
void QQmlContext::setContextProperty(const QString &name, QObject *value)

4.3.1 设置简单的 上下文属性

  • 实例
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickView>
#include <QQmlContext>
int main(int argc, char *argv[]){
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
    QQuickView view;
    view.rootContext()->setContextProperty("Data", QString("设置Qml上下文属性"));
    view.setSource(QUrl(QStringLiteral("qrc:///main.qml")));
    view.show();
    return app.exec();
}
  • 导入相关的类,设置了一个QString类型的属性,这个Data的值可以由加载QML组件的 C++ 程序直接设置,使用的就是setContextProperty()函数。然后,我们就可以直接在qml文件中直接使用Data了,不需要导入任何模块。
import QtQuick 2.9
import QtQuick.Window 2.2
Rectangle {
    width: 640
    height: 480
    color: "lightgray"
    Text {
        id: text
        anchors.centerIn: parent
        text: Data
    }
}

4.3.2 设置对象为上下文属性

  • 设置对象为上下文属性
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickView>
#include <QQmlContext>
#include "mixing.h"
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
    Mixing mixing; // 从堆上分配了一个Mixing对象实例
    QQuickView view;
    view.rootContext()->setContextProperty("mixing", &mixing);
    view.setSource(QUrl(QStringLiteral("qrc:///main.qml")));
    view.show();
    return app.exec();
}
  • 在.qml文件中使用上下文属性中的对象
import QtQuick 2.9
import QtQuick.Window 2.2
//import test.Mixing 1.0
Rectangle {
	id:root
    visible: true
    width: 640
    height: 480
    MouseArea{
        anchors.fill: parent
        acceptedButtons:Qt.LeftButton | Qt.RightButton;
        onClicked: {
            mixing.start()
            mixing.number = 10
        }
    }
    Connections{
        target: mixing
        onColorChanged: {
            root.color = color
            mixing.stop(color)
        }
        onNumberChanged:{
            console.log("new ball number is", mixing.number) // 10
        }
    }
}
  • 由于去掉了qmlRegisterType() 调用,所以在 main.qml中不能再访问Mixing类了,比如说不能通过类名来引用它定义的BALL_COLOR枚举类型了,否则会出现报错:“ReferenceError: Mixing is not defined”
  • 除了枚举类型的值不可以调用之外,其他的属性,以及关联的信号和槽函数,以及用Q_INVOKABLE 宏修饰的方法都是可以继续使用的。

4.4 C++类访问QML(C++=>QML)

  • C++ 访问QML的属性、函数和信号
  • 在 C++ 中加载QML文件可以用QQmlComponent或QQuickView,然后就可以在 C++ 中访问QML对象了。QQuickView提供了一个显示用户界面的窗口,而QQmlComponent没有。

4.4.1 在C++中访问QML中的属性

  • 在qml文件中对Window对象添加一个Rectangle,设置objectName为“rect”,这个值是为了在C++中能够找到这个Rectangle。
import QtQuick 2.9
import QtQuick.Window 2.2
import an.qt.Mixing 1.0
Window {
    id:root
    visible: true
    width: 640
    height: 480
    Rectangle {
          objectName: "rect"
          anchors.fill: parent
    }
    MouseArea{
        anchors.fill: parent
        acceptedButtons:Qt.LeftButton | Qt.RightButton;
        onClicked: {
            mixing.start()
            mixing.number = 10
            qmlSignal("这是qml文件中的qml信号")
        }
    }
    Mixing{
        id:mixing
    }
}
  • 在main.cpp文件中加载QML文件并进行组件实例化后,就可以在 C++ 中访问、修改这个实例的属性值了。
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include "mixing.h"
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
    qmlRegisterType<Mixing>("an.qt.Mixing", 1, 0, "Mixing");
    //QQmlApplicationEngine engine;
    //engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    //if (engine.rootObjects().isEmpty())
    //    return -1;
    QQmlEngine engine;
    QQmlComponent compontext(&engine, QUrl(QStringLiteral("qrc:///main.qml")));
    QObject *object = compontext.create();
    qDebug() << "width value is" << object->property("width").toInt();
    object->setProperty("width", 320);
    qDebug() << "height value is" << QQmlProperty::read(object, "height").toInt();
    QQmlProperty::write(object, "height", 240);
    QObject *rect = object->findChild<QObject*>("rect");
    if(rect) {
        rect->setProperty("color", "orange");
    }
    return app.exec();
}
  • 使用QObject::property()/setProperty()来读取、修改width属性值。
  • 使用QQmlProperty::read()/write()来读取、修改height属性值。
  • 有时候,QML组件是一个复杂的树型结构,包含兄弟组件和孩子组件,我们可以使用QObject::findchild()/findchildren()来查找。如上面的代码中,我们查找名字为rect的孩子组件,如果找到的话就将其颜色设置为橘黄色。

4.4.2 在C++中访问QML中的函数与信号

  • 在 C++ 中,使用 QMetaObject::invokeMethod() 可以调用QML中的函数,它 是个静态方法,其函数原型如下:
bool QMetaObject::invokeMethod(
     QObject * obj,              // 被调用对象的指针
     const char * member,        // 方法名字
     Qt::ConnectionType type,    // 连接类型
     QGenericReturnArgument ret, // 用来接收返回值
     QGenericArgument val0 = QGenericArgument( 0 ),  // 传递给被调用方法的参数
     QGenericArgument val1 = QGenericArgument(), 
     QGenericArgument val2 = QGenericArgument(), 
     QGenericArgument val3 = QGenericArgument(), 
     QGenericArgument val4 = QGenericArgument(), 
     QGenericArgument val5 = QGenericArgument(), 
     QGenericArgument val6 = QGenericArgument(), 
     QGenericArgument val7 = QGenericArgument(), 
     QGenericArgument val8 = QGenericArgument(), 
     QGenericArgument val9 = QGenericArgument()) 
  • 它的返回值如果为true则表明调用成功,返回false,则说明参数不正确或被调用函数名错误。
  • 对于要传递给被调用方法的参数,使用QGenericArgument来表示,原型如下:
QGenericArgument           Q_ARG(Type, const Type & value)
  • 对于返回类型来说,使用QGenericReturnArgument表示,你可以使用 Q_RETURN_ARG 宏来构造一个接收返回指的参数,原型如下:
QGenericReturnArgument     Q_RETURN_ARG(Type, Type & value)  
  • 上述是方法的调用,信号又是如何传递到 C++ 中的呢?更简单了,使用使用 QObject::connect() 可以连接QML中的信号,connect()共有四个重载函数,它们都是静态函数。必须使用SIGNAL()宏来声明信号,SLOT()宏声明槽函数。
  • 使用 QObject::disconnect() 可以解除信号与槽函数的连接。
  • 在qml文件中添加一个信号和方法:
import QtQuick 2.9
import QtQuick.Window 2.2
import an.qt.Mixing 1.0
Window {
    id:root
    visible: true
    width: 640
    height: 480
    signal qmlSignal(string message)
    onQmlSignal: console.log("这是一个信号:",message)
    function qmlFunction(parameter)    {
        console.log("这是一个方法:",parameter)
        return "function from qml"
    }
    Rectangle {
          objectName: "rect"
          anchors.fill: parent
    }

    MouseArea{
        anchors.fill: parent
        acceptedButtons:Qt.LeftButton | Qt.RightButton;
        onClicked: {
            mixing.start()
            mixing.number = 10
            qmlSignal("这是qml文件中的qml信号")
        }
    }
    Mixing{
        id:mixing
    }
}
  • 信号:定义了qmlSignal信号,参数为message,当单击时,会输出message的值。用法很简单。
  • 方法:首先方法的名字是qmlFunction,它的参数为parameter,当调用此方法时,会输出parameter的值,同时返回"function from qml"
  • 修改main.cpp文件,调用信号和方法
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include "mixing.h"
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
    qmlRegisterType<Mixing>("test.Mixing", 1, 0, "Mixing");
    //QQmlApplicationEngine engine;
    //engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    //if (engine.rootObjects().isEmpty())
    //    return -1;
    QQmlEngine engine;
    QQmlComponent compontext(&engine, QUrl(QStringLiteral("qrc:///main.qml")));
    QObject *object = compontext.create();
    qDebug() << "width value is" << object->property("width").toInt();
    object->setProperty("width", 320);
    qDebug() << "height value is" << QQmlProperty::read(object, "height").toInt();
    QQmlProperty::write(object, "height", 240);
    QObject *rect = object->findChild<QObject*>("rect");
    if(rect) {
        rect->setProperty("color", "orange");
    }
    QVariant returnedValue;
    QVariant message = "Hello from c++";
    QMetaObject::invokeMethod(object,"qmlFunction",
                              Q_RETURN_ARG(QVariant,returnedValue),
                              Q_ARG(QVariant,message));
    qDebug() << "returnedValue is " << returnedValue.toString();
    Mixing mixing;
    QObject::connect(object, SIGNAL(qmlSignal(QString)),
                         &mixing, SLOT(cppSlot(QString)));
    return app.exec();
}

5. 常用知识

5.1 引用外部动态库

  • 在主程序的pro文件中,增加如下两行,把头文件和库文件引用进来。
  INCLUDEPATH += /root/Downloads/testlib
  LIBS += -L/root/Downloads/testlib -ltestlib
  • INCLUDEPATH += 后面写so的头文件的路径
  • LIBS += -L后面写lib文件的路径,-l后面是库的项目名称
  • 注意:
    • -l不要带上so,或者其他so.1
    • -L后面直接写路径,不要有空格
    • 建议头文件从原项目拷贝出来,放到主项目目录下,然后写相对连接来引用。

参考:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值