【实操干货】如何开始用Qt Widgets编程?(三)

Qt 是目前最先进、最完整的跨平台C++开发工具。它不仅完全实现了一次编写,所有平台无差别运行,更提供了几乎所有开发过程中需要用到的工具。如今,Qt已被运用于超过70个行业、数千家企业,支持数百万设备及应用。

在本文中,我们通过使用C++和Qt Widgets模块实现一个简单的记事本应用程序来学习基本的Qt知识,该应用程序是一个小型的文本编辑器,允许您创建文本文件、保存、打印或重新打开并在此编辑它,还可以设置要使用的字体。

在上文中(点击这里回顾>>),我们为大家介绍了主源文件的生成、如何开始设计用户界面,本文将为大家详细介绍设计用户界面的具体步骤。

点击获取Qt Widget组件下载(Q技术交流:166830288)

设计一个用户界面
使用Qt Designer(设计器)

向导创建一个使用QMainWindow的应用程序,它有自己的布局,您可以在其中添加菜单栏、dock小部件、工具栏和状态栏。中心区域可以被任何类型的小部件占用,向导将Notepad小部件放在那里。

Qt Designer中添加小部件:

  1. 在Qt Creator编辑模式下,双击记事本,在集成的Qt设计器中启动该文件。
  2. 将小部件文本编辑器(QTextEdit)拖放到表单中。
  3. 按Ctrl+A(或Cmd+A)选择小部件,然后单击Lay out Vertically(或按Ctrl+L)应用垂直布局(QVBoxLayout)。
  4. 按Ctrl+S(或Cmd+S)保存更改。

UI现在看起来像下面的Qt Designer:

您可以在代码编辑器中查看生成的XML文件:

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Notepad</class>
<widget class="QMainWindow" name="Notepad">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>400</height>
</rect>
</property>
<property name="windowTitle">
<string>Notepad</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextEdit" name="textEdit"/>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
...

下面一行包含XML声明,它指定了文档中使用的XML版本和字符编码:

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>

文件的其余部分指定了一个UI元素,该元素定义了一个Notepad小部件:

XML 复制代码
<ui version="4.0">

UI文件与Notepad类的头文件和源文件一起使用,我们将在后面的小节中查看UI文件的其余部分。

Notepad Header文件

向导为Notepad类生成了一个头文件,其中包含必要的#includes、构造函数、析构函数和UI对象。该文件如下所示:

cpp 复制代码
#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui {
class Notepad;
}
QT_END_NAMESPACE

class Notepad : public QMainWindow
{
Q_OBJECT

public:
explicit Notepad(QWidget *parent = nullptr);
~Notepad();

private:
Ui::Notepad *ui;
QString currentFile;
};

下面这行包括QMainWindow,它提供了一个主应用程序窗口:

下面几行在UI命名空间中声明Notepad类,这是uic工具从.ui文件生成的UI类的标准命名空间:

cpp 复制代码
namespace Ui {
class Notepad;
}

类声明包含Q_OBJECT宏,它必须首先出现在类定义中,并将类声明为QObject。当然它也必须继承QObject,QObject为一个普通的c++类添加了一些功能。值得注意的是,类名和槽名可以在运行时查询,还可以查询槽的参数类型并调用它。

cpp 复制代码
class Notepad : public QMainWindow
{
Q_OBJECT

下面几行声明了一个构造函数,它有一个默认实参parent,值0表示该小部件没有父部件(它是顶级小部件)。

cpp 复制代码
public:
explicit Notepad(QWidget *parent = nullptr);

下面一行声明了一个虚析构函数来释放对象在其生命周期中获得的资源,根据c++的命名约定,析构函数具有与其关联的类相同的名称,并以波浪号(~)作为前缀。在QObject中,析构函数是虚函数,以确保在通过指向基类的指针删除对象时正确调用派生类的析构函数。

cpp 复制代码
~Notepad();

下面几行声明了一个成员变量,它是指向Notepad UI类的指针。成员变量与特定的类相关联,并且它的所有方法都可以访问。

cpp 复制代码
private:
Ui::Notepad *ui;
QString currentFile;
};
Notepad源文件

向导为记事本类生成的源文件如下所示:

cpp 复制代码
#include "notepad.h"
#include "ui_notepad.h"

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

}

以下几行包括由向导生成的记事本类头文件和由UI工具生成的UI头文件:

cpp 复制代码
#include "notepad.h"
#include "ui_notepad.h"

下面一行定义了Notepad的构造函数:

cpp 复制代码
Notepad::Notepad(QWidget *parent) :

下面这行调用QMainWindow构造函数,它是Notepad类的基类:

cpp 复制代码
QMainWindow(parent),

下面这行代码创建了UI类实例并将其赋值给UI成员:

cpp 复制代码
ui(new Ui::Notepad)

下面这行设置了UI:

cpp 复制代码
{
ui->setupUi(this);

在析构函数中,删除UI:

cpp 复制代码
Notepad::~Notepad()
{
delete ui;
}
项目文件

向导为我们生成以下项目文件CMakeLists.txt:

cpp 复制代码
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause

cmake_minimum_required(VERSION 3.16)
project(notepad LANGUAGES CXX)

if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()

set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/notepad")

find_package(Qt6
REQUIRED COMPONENTS Core Gui Widgets
OPTIONAL_COMPONENTS PrintSupport
)

qt_standard_project_setup()

qt_add_executable(notepad
main.cpp
notepad.cpp notepad.h notepad.ui
)

set_target_properties(notepad PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)

target_link_libraries(notepad PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)

if(TARGET Qt6::PrintSupport)
target_link_libraries(notepad PRIVATE Qt6::PrintSupport)
endif()

# Resources:
set(notepad_resource_files
"images/bold.png"
"images/copy.png"
"images/create.png"
"images/cut.png"
"images/edit_redo.png"
"images/edit_undo.png"
"images/exit.png"
"images/font.png"
"images/info.png"
"images/italic.png"
"images/new.png"
"images/open.png"
"images/paste.png"
"images/pencil.png"
"images/print.png"
"images/save.png"
"images/save_as.png"
"images/underline.png"
)

qt_add_resources(notepad "notepad"
PREFIX
"/"
FILES
${notepad_resource_files}
)

install(TARGETS notepad
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

项目文件指定项目中包含的源文件、头文件和UI文件。

相关推荐
秃头佛爷27 分钟前
Python学习大纲总结及注意事项
开发语言·python·学习
阿伟*rui28 分钟前
配置管理,雪崩问题分析,sentinel的使用
java·spring boot·sentinel
待磨的钝刨28 分钟前
【格式化查看JSON文件】coco的json文件内容都在一行如何按照json格式查看
开发语言·javascript·json
XiaoLeisj2 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
paopaokaka_luck2 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
dayouziei2 小时前
java的类加载机制的学习
java·学习
励志成为嵌入式工程师3 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉4 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer4 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq4 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端