We built an easy counter by Qt, and here are details.


Former Setup

使用 Qt Creator 18.0.2 (Community) 版本,创建一个 Qt Widgets Application ,使用 CMake for Qt 5 and Qt 6 进行搭建。


Project Tree

一个新创建的项目会有这几个文件,这是他们的树状结构:

./
├── CMakeList.txt
├── main.cpp
├── mainwindow.cpp
├── mainwindow.h
└── mainwindow.ui

在项目文件夹打开会看到这些文件,但在 Qt Creator 的项目结构有时并非如此,我们可能会看到 Forms, Header Files, Source Files 之类的文件夹,我个人将其理解为一种便于分类的假性文件夹。


Files Explantion

CMakesList.txt 这是项目的配置文件,用来描述项目文件之间的关系,也包括使用什么编译器编译,工程入口在哪儿,等等。

mainwindow.ui 这是项目的界面文件(User Interface),当然一般不会直接写源代码,双击源文件就可以进入Qt准备好的可视化界面设计。

main.cpp 顾名思义,这是项目的入口文件。

剩下的两个文件(mainwindow.h, mainwindow.cpp)基本就是项目的主体,他们相互调用,相互帮助。为了避免单个文件内容过大,头文件用来声明函数,源文件则用来编写函数。

CMakeList.txt

代码如下,这是项目构建时自己生成的。

cmake_minimum_required(VERSION 3.16)

project(HelloWorld VERSION 0.1 LANGUAGES CXX)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)

set(PROJECT_SOURCES
        main.cpp
        mainwindow.cpp
        mainwindow.h
        mainwindow.ui
)

if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
    qt_add_executable(HelloWorld
        MANUAL_FINALIZATION
        ${PROJECT_SOURCES}
    )
# Define target properties for Android with Qt 6 as:
#    set_property(TARGET HelloWorld APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
#                 ${CMAKE_CURRENT_SOURCE_DIR}/android)
# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
else()
    if(ANDROID)
        add_library(HelloWorld SHARED
            ${PROJECT_SOURCES}
        )
# Define properties for Android with Qt 5 after find_package() calls as:
#    set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
    else()
        add_executable(HelloWorld
            ${PROJECT_SOURCES}
        )
    endif()
endif()

target_link_libraries(HelloWorld PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)

# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
# If you are developing for iOS or macOS you should consider setting an
# explicit, fixed bundle identifier manually though.
if(${QT_VERSION} VERSION_LESS 6.1.0)
  set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.HelloWorld)
endif()
set_target_properties(HelloWorld PROPERTIES
    ${BUNDLE_ID_OPTION}
    MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
    MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
    MACOSX_BUNDLE TRUE
    WIN32_EXECUTABLE TRUE
)

include(GNUInstallDirs)
install(TARGETS HelloWorld
    BUNDLE DESTINATION .
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

if(QT_VERSION_MAJOR EQUAL 6)
    qt_finalize_executable(HelloWorld)
endif()

main.cpp

代码如下,这是也项目构建时自己生成的。

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

mainwindow.h

代码如下,这是也项目构建时自己生成的。

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void onPlusClicked();
    void onMinusClicked();

private:
    Ui::MainWindow *ui;
    int m_count=0;
};
#endif // MAINWINDOW_H

mainwindow.cpp

代码如下,这是也项目构建时自己生成的。

#include "mainwindow.h"
#include "./ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    connect(ui->btn1, &QPushButton::clicked, this, &MainWindow::onPlusClicked);
    connect(ui->btn2, &QPushButton::clicked, this, &MainWindow::onMinusClicked);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::onPlusClicked()
{
    m_count++;
    ui->label->setText(QString::number(m_count));
}

void MainWindow::onMinusClicked()
{
    m_count--;
    ui->label->setText(QString::number(m_count));
}

Building...That's all for now.