龙空技术网

Qt QML和QWidget混合编程(面试亮点)

QT教程 329

前言:

现在姐妹们对“qt写游戏引擎”大体比较关心,看官们都需要剖析一些“qt写游戏引擎”的相关资讯。那么小编同时在网上网罗了一些对于“qt写游戏引擎””的相关内容,希望兄弟们能喜欢,我们一起来学习一下吧!

本文转载自:公众号:Qt历险记

QML的应用场景

1. 移动应用程序开发:QML可以用于开发移动应用程序,包括iOS、Android和其他移动平台。

2. 桌面应用程序开发:QML可以用于开发桌面应用程序,包括Windows、Mac和Linux系统。

3. 嵌入式系统开发:QML可以用于开发嵌入式系统,包括智能家居设备、工业控制设备等。

4. 游戏开发:QML可以用于开发2D和3D游戏,利用Qt Quick内置的图形引擎提供丰富的图形效果和动画支持。

5. 用户界面设计:QML可以用于设计和开发各种用户界面,包括交互式图表、数据可视化、动态效果等。

6. 互联网应用程序开发:QML可以用于开发互联网应用程序,包括Web应用、云应用等。

Qt的未来趋势是更加注重在QML和Qt Quick上,并逐渐减少对QWidget的支持。虽然Qt Widget仍然是许多项目的基础,但Qt公司已经在向开发人员推荐使用QML和Qt Quick来构建现代、动态的用户界面。

Qt Quick和QML使得UI开发更加灵活和高效,能够更好地满足现代用户界面的需求。随着移动设备和嵌入式系统的兴起,QML和Qt Quick也更适合这些平台,并且能够为开发人员提供更好的用户体验。

尽管如此,Qt仍然对QWidget提供支持,并且可以在现有的项目中继续使用。然而,Qt未来的发展方向似乎更青睐于QML和Qt Quick,并且Qt公司也在逐渐将重点放在这些技术上。因此,未来趋势更可能是推动开发者们更多地使用QML和Qt Quick来构建应用程序的用户界面,而QWidget在一些传统项目中可能仍然会被使用。

项目QML和CPP交互

开发平台:windows

Qt工具:Qt 5.14.2

创建的项目

QmlCallCpp.pro

QT += quickCONFIG += c++11 utf8_source# The following define makes your compiler emit warnings if you use# any Qt feature that has been marked deprecated (the exact warnings# depend on your compiler). Refer to the documentation for the# deprecated API to know how to port your code away from it.DEFINES += QT_DEPRECATED_WARNINGS# You can also make your code fail to compile if it uses deprecated APIs.# In order to do so, uncomment the following line.# You can also select to disable deprecated APIs only up to a certain version of Qt.#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0SOURCES += \        CppObject.cpp \        main.cppRESOURCES += qml.qrc# Additional import path used to resolve QML modules in Qt Creator's code modelQML_IMPORT_PATH =# Additional import path used to resolve QML modules just for Qt Quick DesignerQML_DESIGNER_IMPORT_PATH =# Default rules for deployment.qnx: target.path = /tmp/$${TARGET}/binelse: unix:!android: target.path = /opt/$${TARGET}/bin!isEmpty(target.path): INSTALLS += targetHEADERS += \    CppObject.h
main.cpp
#include <QGuiApplication>#include <QQmlApplicationEngine>#include <QQmlContext>#include "CppObject.h"#include <QDebug>int main(int argc, char *argv[]){    // Qt::AA_EnableHighDpiScaling属性用于启用高DPI(高分辨率显示)缩放支持。    // 在应用程序窗口显示在高DPI屏幕上时,启用此属性将确保应用程序窗口能够正确缩放和渲染以适应高分辨率屏幕的显示。    // 这意味着应用程序将具有更好的外观和可用性,特别是在高分辨率显示器上使用时。    /* 在嵌入式设备上使用`QApplication::setAttribute(Qt::AA_EnableHighDpiScaling)`可能不太合适,具体取决于嵌入式设备的屏幕分辨率和硬件性能。        嵌入式设备通常具有较小的屏幕尺寸和较低的分辨率,因此启用高DPI缩放可能会导致应用程序界面过于缩小,导致用户体验不佳。        另外,一些嵌入式设备的硬件性能可能有限,无法有效地处理高DPI缩放所带来的额外渲染负担,导致性能下降和能耗增加。        因此,在嵌入式设备上,需要仔细评估设备的屏幕分辨率、性能和用户体验需求,权衡是否启用高DPI缩放。        如果设备具有高分辨率屏幕,较高的性能和用户体验需求,则可以考虑启用高DPI缩放,否则可能需要禁用该选项。*/    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);    QGuiApplication app(argc, argv); // 创建用户界面APP    //qmlRegisterType注册C++类型至QML    //arg1:import时模块名    //arg2:主版本号    //arg3:次版本号    //arg4:QML类型名    qmlRegisterType<CppObject>("MyCppObject",1,0,"CppObject");    // QQmlApplicationEngine是Qt框架中用于加载QML文件的应用程序引擎。    // 它通常用于Qt Quick应用程序中,用于加载和管理QML文件并且启动应用程序的执行。    QQmlApplicationEngine engine;    //也可以注册为qml全局对象    //engine.rootContext()->setContextProperty("cppObj",new CppObject(qApp));    qDebug()<<"开始加载界面";    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));    if (engine.rootObjects().isEmpty())        return -1;    return app.exec();}
CppObject.h
#ifndef CPPOBJECT_H#define CPPOBJECT_H#include <QObject>//派生自QObject//使用qmlRegisterType注册到QML中class CppObject : public QObject{    Q_OBJECT    //注册属性,使之可以在QML中访问--具体语法百度Q_PROPERTY    Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)    Q_PROPERTY(int year READ getYear WRITE setYear NOTIFY yearChanged)    /* Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged):     * 这一行代码用于声明一个名为name的属性,它的类型是QString。     * READ, WRITE和NOTIFY分别指定了读取、写入和属性变化时的信号。     * 这表示对于name属性,您可以使用getName函数来读取属性的值,使用setName函数来设置属性的值,     * 而nameChanged信号在属性值变化时将被发射。*/public:    explicit CppObject(QObject *parent = nullptr);    //通过Q_INVOKABLE宏标记的public函数可以在QML中访问    Q_INVOKABLE void sendSignal();//功能为发送信号  cpp->QML    // 给类属性添加访问方法--myName    void setName(const QString &name);    QString getName() const;    // 给类属性添加访问方法--myYear    void setYear(int year);    int getYear() const;signals:    // 信号可以在QML中访问    void cppSignalA();//一个无参信号  QML->CPP    void cppSignalB(const QString &str,int value);//一个带参数信号 QML->CPP    void nameChanged(const QString &name);    void yearChanged(int year);public slots:    // public槽函数可以在QML中访问    void cppSlotA();//一个无参槽函数    void cppSlotB(const QString &str,int value);//一个带参数槽函数    // 姓名改变保存到文件    void nameChangedSlot(const QString &name);private:    // 类的属性    QString myName;    int myYear;};#endif // CPPOBJECT_H
CppObject.cpp
#ifndef CPPOBJECT_H#define CPPOBJECT_H#include <QObject>//派生自QObject//使用qmlRegisterType注册到QML中class CppObject : public QObject{    Q_OBJECT    //注册属性,使之可以在QML中访问--具体语法百度Q_PROPERTY    Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)    Q_PROPERTY(int year READ getYear WRITE setYear NOTIFY yearChanged)    /* Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged):     * 这一行代码用于声明一个名为name的属性,它的类型是QString。     * READ, WRITE和NOTIFY分别指定了读取、写入和属性变化时的信号。     * 这表示对于name属性,您可以使用getName函数来读取属性的值,使用setName函数来设置属性的值,     * 而nameChanged信号在属性值变化时将被发射。*/public:    explicit CppObject(QObject *parent = nullptr);    //通过Q_INVOKABLE宏标记的public函数可以在QML中访问    Q_INVOKABLE void sendSignal();//功能为发送信号  cpp->QML    // 给类属性添加访问方法--myName    void setName(const QString &name);    QString getName() const;    // 给类属性添加访问方法--myYear    void setYear(int year);    int getYear() const;signals:    // 信号可以在QML中访问    void cppSignalA();//一个无参信号  QML->CPP    void cppSignalB(const QString &str,int value);//一个带参数信号 QML->CPP    void nameChanged(const QString &name);    void yearChanged(int year);public slots:    // public槽函数可以在QML中访问    void cppSlotA();//一个无参槽函数    void cppSlotB(const QString &str,int value);//一个带参数槽函数    // 姓名改变保存到文件    void nameChangedSlot(const QString &name);private:    // 类的属性    QString myName;    int myYear;};#endif // CPPOBJECT_H
main.qml
import QtQuick 2.9import QtQuick.Window 2.9import QtQuick.Controls 2.9//引入我们注册的模块import MyCppObject 1.0/*在 QML 中,信号是不区分大小写的。这意味着当您定义一个信号时,无论是使用大写、小写或混合大小写的方式命名,都将被视为同一个信号。例如,在 QML 中,以下两种方式定义的信号将被视为相同的信号:```qmlsignal mySignal``````qmlsignal MYSIGNAL```因此,您可以在 QML 中自由选择信号的命名方式,而不必担心大小写问题。*/// 代码执行顺序上->下Window {    id: root    visible: true    width: 600    height: 100    title: qsTr("QML调用Cpp对象:微信公众号:Qt历险记")    color:"gray"    // QML中的信号声明    signal qmlSignalA    signal qmlSignalB(string str,int value)    // 鼠标点击区域    MouseArea{        anchors.fill: parent        acceptedButtons: Qt.LeftButton | Qt.RightButton        // 测试时点击左键或右键        onClicked: {            if(mouse.button === Qt.LeftButton){                console.log('==============QML====================')                console.log('----qml 点击左键:Cpp发射信号')                console.log('----qml name 改变前' + cpp_obj.name)                cpp_obj.name=inputField.text     // 修改属性会触发set函数,获取值会触发get函数                console.log('----qml year改变前' + cpp_obj.year)    // 修改属性会触发getName函数,获取值会触发get函数                cpp_obj.year= Math.floor(Math.random() * 100) // 生成0到99之间的随机整数(Math.random() 0.0-1.0) 向下取整                cpp_obj.sendSignal()                 // 调用Q_INVOKABLE宏标记的函数            }else{                console.log('----qml 点击右键:QML发射信号')                root.qmlSignalA()                root.qmlSignalB('Qt历险记',1992)            }        }    }    /* 通过输入文本改变name*/    Rectangle {           width: parent.width           height: 40           color: "lightgray"           TextField {               id: inputField               width: 200               anchors.centerIn: parent // 在矩形的中间               placeholderText: "please input your  name" // 占位符文本           }       }    // 作为一个QML对象 创建的CPP构造函数被执行    CppObject{        id:cpp_obj        //也可以像原生QML对象一样操作,增加属性之类的        property int namecounts: 0        property int yearcounts: 0        onNameChanged: {            namecounts++            console.log('qml onNameChanged', "第"+ namecounts +"次改变\n\n")        }        onYearChanged: {            yearcounts++            console.log('qml onYearChanged',"第"+ yearcounts +"次改变\n\n")        }        onNamecountsChanged: {            console.log('==============QML====================')            console.log('qml onNamecountsChanged',namecounts)        }        onYearcountsChanged: {            console.log('==============QML====================')            console.log('qml onYearcountsChanged',yearcounts)        }    }    //组件加载完成执行    Component.onCompleted: {        console.log('================Component.onCompleted')        //关联信号与信号处理函数的方式同QML中的类型        //Cpp对象的信号关联到Qml        //cpp_obj.onCppSignalA.connect(function(){console.log('qml signalA process')})        // 表示当 cpp_obj 对象的 onCppSignalA 信号被触发时,会执行QML中的一个匿名函数(也称为lambda表达式)CPP->QML        cpp_obj.onCppSignalA.connect(()=>console.log('=============qml signalA process')) //js的lambda        cpp_obj.onCppSignalB.connect(processB)        // 当 QML 的 onQmlSignalA/B 信号被触发时,会调用 C++ 对象 cpp_obj 的 cppSlotA/B 槽函数。 QML->CPP        root.onQmlSignalA.connect(cpp_obj.cppSlotA)        root.onQmlSignalB.connect(cpp_obj.cppSlotB)    }    //定义的函数可以作为槽函数    function processB(str,value){        console.log('=============qml function processB',"name = "+str," year = "+value)    }}
运行结果

输入文本,点击下方灰黑色区域调试如下:

标签: #qt写游戏引擎