QT基础——核心模块QtCore

qt core 提供了元对象系统,扩展了c++ 在元对象系统的基础上,qt又提供了信号/槽、property以及对象树等特性

  • The Meta-Object System
  • The Property System
  • Object Model
  • Object Trees & Ownership
  • Signals & Slots

Meta-Object系统

较复杂,暂时跳过

Property 系统

例子:

class MyClass : public QObject
{
    Q_OBJECT
    Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged)

public:
    MyClass(QObject *parent = nullptr);
    ~MyClass();

    enum Priority { High, Low, VeryHigh, VeryLow };
    Q_ENUM(Priority)

    void setPriority(Priority priority)
    {
        m_priority = priority;
        emit priorityChanged(priority);
    }
    Priority priority() const
    { return m_priority; }

signals:
    void priorityChanged(Priority);

private:
    Priority m_priority;
};

信号 & 槽

一个普通的c++类:

class Counter
{
public:
    Counter() { m_value = 0; }

    int value() const { return m_value; }
    void setValue(int value);

private:
    int m_value;
};

添加信号槽:

#include <QObject>

class Counter : public QObject
{
    Q_OBJECT

public:
    Counter() { m_value = 0; }

    int value() const { return m_value; }

public slots:
    void setValue(int value);

signals:
    void valueChanged(int newValue);

private:
    int m_value;
};

信号 & 槽的连接用connect函数:

connect(sender, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(Qbject*)));
connect(sender, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed()));
connect(sender, SIGNAL(destroyed()), this, SLOT(objectDestroyed()));

下面的例子绑定了QProcess的finished信号和afterBuild函数,

//编译keil工程
void ExeCmd::buildProj(QString uv4, QString home){
    qDebug() << "Enter build buildProj()";
    if(uv4 == nullptr || home== nullptr){
        qDebug() << "param invalid";
        return;
    }
    if(!QFile::exists(uv4)){
        qDebug() << "uv4 not exit";
        return;
    }
    QProcess *myProcess = new QProcess();
    connect(myProcess, &QProcess::finished, this, &ExeCmd::afterBuild);
    QStringList arguments;
    arguments << "-r" << home+ "/App.uvproj" << "-t" << "App";
    myProcess->start(uv4, arguments);
}

//编译完成之后拷贝二进制文件到缓存目录
void ExeCmd::afterBuild(int val){
    qDebug()<< "Enter afterBuild()" << val;
    QProcess* obj = (QProcess*)sender();
    qDebug()<<"result:" << QString::fromUtf8(obj->readAll());
    delete obj;

    //copy hex file to temp
    CfgFile cf = CfgFile();
    copyHexToTempFolder(cf.getTargetPath());
}

资源系统

https://doc.qt.io/qt-6/resources.html

Qt资源系统是一种独立于平台的机制,用于在应用程序中传送资源文件。如果您的应用程序始终需要一组特定的文件(如图标、翻译文件、图像),并且您不想使用特定于系统的方法打包和查找这些资源,请使用它。
最常见的是,资源文件嵌入到应用程序可执行文件中,或者嵌入到应用程序可执行文件加载的库和插件中。或者,资源文件也可以存储在外部资源文件中。

资源编译器rcc

资源系统基于Qt的rcc资源编译器,构建系统和Qt运行时API之间的密切合作。
rcc读取资源文件(图标、翻译文件、图像)并翻译成 C++ 或 Python 源文件,或者翻译成文件 *.rcc
默认情况下,rcc将生成C++源代码,然后将其编译为可执行文件或库的一部分。
-g选项可以指定生成类型,-g, --generator <cpp|python|python2> Select generator

Qt资源集合文件 .qrc

是一个xml文件,例子:

<RCC>
    <qresource prefix="/">
        <file>images/copy.png</file>
        <file>images/cut.png</file>
        <file>images/new.png</file>
        <file>images/open.png</file>
        <file>images/paste.png</file>
        <file>images/save.png</file>
    </qresource>
</RCC>

cmake使用rcc的第一种方式

在cmake中使用qrc文件非常方便,启用CMAKE_AUTORCC然后直接把qrc文件当成代码源文件即可:

set(CMAKE_AUTORCC ON)

qt_add_executable(my_app
    application.qrc
    main.cpp
)

CMAKE_AUTORCC是cmake提供的支持,而不是qt自定义的类型,参考 https://cmake.org/cmake/help/latest/prop_tgt/AUTORCC.html

cmake使用rcc的第二种方式

除了使用CMAKE_AUTORCC的方式,还可以使用qt提供的函数qt_add_resources:

qt_add_resources(my_app "app_images"
    PREFIX "/"
    FILES
        images/copy.png
        images/cut.png
        images/new.png
        images/open.png
        images/paste.png
        images/save.png
)

使用这种方法的好处是不用编写qrc文件

引用添加到qrc的文件

在使用qrc的方式中,如果资源文件已经被添加到qrc文件,那么在代码中是不需要使用真实路径来引用文件的,有两种方式引用文件(Path 和 URL,都是资源系统内部相对的):

举个例子,在qml中Image对象显示一张照片,需要赋值source属性,而Image.source是url类型:

那么代码中就这样写:

Image {
  Layout.preferredHeight: 100
  Layout.preferredWidth: 100
  //也可以简写成 source: "/imgs/rebuild.png"
  source: "qrc:/imgs/rebuild.png"
}

c++代码中函数参数是url类型的同样也可以:

 QQmlApplicationEngine engine;
 engine.load(QUrl("qrc:/myapp/main.qml"));

以上都是使用url,path的方式也举个例子:

cutAct = new QAction(QIcon(":/images/cut.png"), tr("Cu&t"), this);

QIcon接收参数是QString fileName,这里直接赋值的是资源系统提供的path而不是真实的文件path。

使用path的例子还有QTranslator,如果我们有两份翻译文件en_US.qmzh_CN.qm把他们添加到qrc之后就可以:

void QmlLanguage::setLanguage(int indexOfLanguage)
{
    QTranslator translator;
    if (indexOfLanguage == 0)
    {
        translator.load(":/en_US.qm");
    }else if (indexOfLanguage == 1) {
        translator.load(":/zh_CN.qm");
    }else{
        translator.load(":/en_US.qm");
    }
    //QGuiApplication &app
    app->installTranslator(&translator);
    //QQmlApplicationEngine& engine
    engine->retranslate();
}

qrc支持的类型

上文中已经出现过的有图片和翻译文件(.qm),除此之外还支持qml文件,比如我们自定义的控件

自定义控件的使用方式:
(1)编写qml文件
(2)添加到cmake

qt_add_qml_module(PerfTestTool
    URI App
    VERSION 1.0
    QML_FILES main.qml ./controls/XBtn.qml ./controls/XTextField.qml
)

(3)import 路径 :import "./controls",这是用真实路径的方式
qml文件添加到qrc之后,还可以用url的方式:import "qrc:/controls"

QtCore提供的c++类

https://doc.qt.io/qt-6/qtcore-module.html

国际化

首先通过工具lupdate把qml文件抽出来包含qsTr()的文本

lupdate main.qml -ts zh_CN.ts en_us.ts

ts文件其实是xml,定位qsTr在qml文件的位置

然后使用工具Linguist打开ts文件,翻译成目标语言

翻译完成后,发布,就可以得到qm文件

qm文件不是文本文件

再然后把qm文件进资源系统,就可以用c++切换语言了

void QmlLanguage::setLocalLanguage(){
    QTranslator translator;
    QLocale locale;
    if( locale.language() == QLocale::English ) {
        translator.load(":/en_us.qm");
    }
    else if( locale.language() == QLocale::Chinese ) {
        translator.load(":/zh_CN.qm");
    }
    m_app->installTranslator(&translator);
    //重新载入语言包
    m_engine->retranslate();
}
posted @ 2023-01-05 23:08  feipeng8848  阅读(477)  评论(0编辑  收藏  举报