Qt Quick基础用法+基本知识

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后面直接写路径,不要有空格
    • 建议头文件从原项目拷贝出来,放到主项目目录下,然后写相对连接来引用。

参考:

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《QtQt Quick开发实战精解》是一本关于Qt开发的实用指南。Qt是一套跨平台的C++图形界面应用程序开发框架,被广泛应用于开发桌面应用、移动应用和嵌入式系统。Qt QuickQt框架下的一个模块,它专注于快速开发漂亮、流畅的用户界面。 该书从理论和实践两个方面介绍了QtQt Quick的基本概念和开发技巧。首先,作者讲解了Qt基础知识,包括Qt的工具链、对象模型、信号与槽机制等。接着,书中详细介绍了Qt Quick的相关内容,包括Qt Quick的语法、界面元素、布局方式等。此外,书中还介绍了QtQt Quick的常用控件、多线程编程、网络通信等高级技术。 这本书通过丰富的实例和案例,让读者能够更好地理解QtQt Quick开发原理和实践方法。例如,书中提供了一些常见应用场景下的实战案例,如开发一个跨平台的音乐播放器、绘制一个实时曲线图等。通过参考这些案例,读者可以学会如何使用QtQt Quick进行各种应用开发。 此外,书中还对QtQt Quick的性能优化和调试技巧进行了介绍。它提供了一些常见的性能问题和解决方案,帮助开发者优化和调试他们的应用程序。 总的来说,《QtQt Quick开发实战精解》是一本非常实用的开发指南,能够帮助读者快速掌握QtQt Quick开发技巧,并且能够应用于实际项目中。无论是对于初学者还是有一定经验的开发者来说,这本书都是一本值得推荐的学习资料。 ### 回答2: QtQt Quick开发实战精解是一本与Qt以及Qt Quick相关的开发实践指南。Qt是跨平台的C++应用程序开发框架,而Qt Quick是一种用于创建流畅的用户界面的用户界面技术。 该书的主要内容包括Qt基础知识、Qt Quick基础知识以及在实际项目中如何应用QtQt Quick进行开发。首先,书中介绍了Qt的概念、特点和架构,让读者对Qt有一个全面的了解。然后,书中详细讲解了Qt的常用模块和功能,包括图形界面、网络通信、数据库访问和多线程编程等。读者可以通过学习这些内容,了解如何使用Qt进行各种应用程序的开发。 接下来,该书重点介绍了Qt Quick的知识。Qt QuickQt的一个模块,用于设计和开发现代化的用户界面。它使用QML语言来描述界面,具有快速、灵活和可扩展的特点。书中详细讲解了QML语言的语法和特性,以及如何使用Qt Quick的各种元素和组件进行界面设计。 最后,书中还提供了一些实际项目的案例和示例代码,供读者参考和学习。这些案例涵盖了各种应用领域,包括桌面应用、移动应用和嵌入式应用等。通过阅读这些案例,读者可以学习如何使用QtQt Quick开发各种实际项目,并且能够从中获取一些实战经验和技巧。 总之,QtQt Quick开发实战精解是一本系统而全面的Qt开发指南,对于想要学习和应用QtQt Quick进行开发的读者来说,是一本非常有价值的书籍。无论是初学者还是有一定经验的开发者,都可以从这本书中获得实用的知识和技巧。 ### 回答3: 《QtQt Quick开发实战精解》是一本介绍Qt开发框架和Qt Quick的实战书籍。Qt是一款跨平台的应用程序开发框架,可以帮助开发者轻松构建和部署高质量的应用程序。Qt QuickQt的一部分,是一种用于快速开发现代化用户界面的技术。 这本书以实战为导向,详细介绍了QtQt Quick的各种开发技巧和最佳实践。首先,它介绍了Qt框架的基本概念和原理。读者可以了解到Qt的对象模型、信号与槽机制、事件处理等重要概念,为后续的实践打下坚实的基础。 接下来,书籍还详细介绍了Qt Quick的使用方法。Qt Quick使用QML语言来构建用户界面,可以快速创建现代化和流畅的界面。书籍对于QML语法、组件的使用和定制、动画效果等方面进行了详细的讲解,帮助读者掌握Qt Quick开发技术。 此外,书籍还通过实际项目案例来演示QtQt Quick的应用场景。读者可以学习如何使用QtQt Quick开发各种类型的应用程序,如图形界面应用、嵌入式应用、移动应用等。通过这些实例,读者将学会如何根据需求选择合适的Qt组件和库,以及如何解决实际开发中的常见问题。 总的来说,《QtQt Quick开发实战精解》是一本实用性很强的书籍,适合初学者和有一定经验的开发者阅读。读者可以通过学习这本书,快速入门QtQt Quick开发,提升自己的开发技能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值