第01章 Qt初步

发布时间:2023年12月17日

目录

1.1 QT是什么

1.2 QT的发展历程

1.3QT开发的优势

1.3.1 Windows 下的 GUI 库

1.3.2 Linux 下的 GUI 库

1.3.3 题外话

1.4QT的下载安装

1.4.1 QT的下载

1.4.2 Linux下的安装

1.4.3 windows下安装

1.5第一个QT程序

1.6 可视化UI设计

1.7 代码化UI设计

1.7.1 信号与槽

1.7.2 更彻底的代码化UI设计

1.8 混合方式UI设计

1.9本章常见方法总结


1.1 QT是什么


Qt是一个跨平台的C++开发库,主要用来开发图形用户界面(Graphical User Interface,GUI)程序。 Qt 还存在 Python、Ruby、Perl 等脚本语言的绑定,也就是说可以使用脚本语言开发基于 Qt 的程序。 之所以称之为跨平台是因为Qt 支持的操作系统有很多,例如通用操作系统 Windows、Linux、Unix、 Android、IOS、WinPhone、QNX、VxWorks等等。

Qt 虽然经常被当做一个 GUI 库,用来开发图形界面应用程序,但这并不是 Qt 的全部;Qt 除了可以绘制漂亮的界面(包括控件、布局、交互),还包含很多其它功能,比如多线程、访问数据库、图像处理、音频视频处理、网络通信、文件操作等,这些 Qt 都已经内置了。 1997年,Qt 被用来开发 Linux 桌面环境 KDE,大获成功,使 Qt 成为 Linux 环境下开发 C++ GUI 程序的事实标准。 WPS、YY语音、Skype、豆瓣电台、虾米音乐、淘宝助理、千牛、暴雪的战网客户端、VirtualBox、 Opera、咪咕音乐、Google地图、Adobe Photoshop Album 等知名软件都是使用Qt开发的。 Qt 虽然也支持手机操作系统,但是由于Android本身已经有了Java和Kotlin,IOS本身已经有了Objective-C 和 Swift,所以 Qt 在手机领域的市场份额几乎可以忽略。总起来说,Qt 主要用于桌面程序开发和嵌入式开发。

1.2 QT的发展历程


Qt 最早是 1991 年由挪威的 Eirik Chambe-Eng 和 Haavard Nord 开发的,他们随后于 1994 年 3 月 4 号正式成立奇趣科技公司(Trolltech)。Qt 原本是商业授权的跨平台开发库,在 2000 年奇趣科技公司为开源社区发布了遵循 GPL(GNU General Public License)许可证的开源版本。 在 2008 年,诺基亚公司收购了奇趣科技公司,并增加了 LGPL(GNU Lesser General Public License)的授权模式。诺基亚联合英特尔利用 Qt 开发了全新的智能手机系统 MeeGo,可惜遭遇了微软木马屠城,诺基亚被迫放弃了 MeeGo,而 Qt 商业授权业务也于 2011 年 3 月出售给了芬兰 IT 服务公司 Digia。

Digia 于 2014 年 9 月宣布成立 Qt Company 全资子公司,独立运营 Qt 商业授权业务。目前 Qt 公司大力推广移动平台开发和商业应用,总的来说 Qt 历经曲折,现在算是步入正轨了。

经过 20 多年的发展,Qt 已经成为最优秀的跨平台开发框架之一,在各行各业的项目开发中得到广泛应用。

1.3QT开发的优势


世界上的 GUI 库多如牛毛,有的跨平台,有的专属于某个操作系统;有的只有 UI 功能,有的还融合了网络通信、多媒体处理、数据库访问等底层功能。

1.3.1 Windows 下的 GUI 库

Windows 下的 GUI 解决方案比较多:

  • 基于 C++ 的有 Qt、MFC、WTL、wxWidgets、 DirectUI、Htmlayout;

  • 基于 C# 的有 WinForm、WPF;

  • 基于 Java的有 AWT、Swing;

  • 基于 Pascal 的有 Delphi;

  • 基于Go语言的有 walk 和 electron;

  • 还有国内初露头角的 aardio;

  • Visual Basic 曾经很流行,现在逐渐失去了色彩;

  • 如果你有 Web 开发经验,也可以基于 Webkit 或 Chromium 将网页转换为桌面程序。

没有哪一种方案能够独霸 Windows,使用比较多的编程语言是 C++、C#、Java。

用 Qt 来开发 Windows 桌面程序有以下优点:

  • 简单易学:Qt 封装的很好,几行代码就可以开发出一个简单的客户端,不需要了解 Windows API。

  • 资料丰富:资料丰富能够成倍降低学习成本,否则你只能去看源码,关于 DirectUI、Htmlayout、aardio的资料就很少。

  • 漂亮的界面:Qt 很容易做出漂亮的界面和炫酷的动画,而 MFC、WTL、wxWidgets 比较麻烦。

  • 独立安装:Qt 程序最终会编译为本地代码,不需要其他库的支撑,而 Java 要安装虚拟机,C# 要安装 .NET Framework。

  • 跨平台:如果你的程序需要运行在多个平台下,同时又希望降低开发成本,Qt 几乎是必备的。

Qt 和 MFC的对比:

  • MFC 只能应用在 Windows 平台,而 Qt 是跨平台的,一次编写,到处运行。

  • Qt 已经封装了底层细节,学习 Qt 将会非常简单;而 MFC 只是给 Windows API 加了一层包装,不了解 Windows API 也学不好 MFC

1.3.2 Linux 下的 GUI 库

Linux 下常用的 GUI 库有基于 C++ 的 Qt、GTK+、 wxWidgets,以及基于 Java 的 AWT 和 Swing。其中最著名的就是 Qt 和 GTK+:KDE 桌面系统已经将 Qt 作为默认的 GUI 库,Gnome 桌面系统也将 GTK+ 作为默认的 GUI 库。 相比 GTK+,Qt 的功能更加强大,更新也很快,比较受人们追捧。

1.3.3 题外话

Qt4 时代的主流就是传统组件(或叫控件)编程,所用的语言一般是 C++。 Qt5 诞生之时,正是手机移动设备蓬勃发展的时候, 为了适应手机移动应用开发, Qt5 将 QML 脚本编程提到与传统 C++ 组件编程相同的高度,力推 QML 界面编程,当然 QML 主要用于手机移动应用程序。 QML 包含大量使用手机移动设备的功能模块,比如基本组件(QtQuick 模块)、GPS 定位、渲染特效、蓝牙、NFC、WebKit 等等。 QML 类似于网页设计的 HTML,是一种标记语言,我们可以借助 CSS 对它进行美化,也可以借助 JavaScript 进行交互。有 Web 开发经验的读者学习 QML 将非常轻松。 使用 QML 开发界面主要有以下几个优点:

  • QML 非常灵活,可以做出非常炫酷的效果,例如 QQ、360、迅雷等都不在话下。

  • QML 是标记语言,见名知意,非常容易编写和阅读,大大提高了开发和维护效率。

  • QML 界面简洁大气,有很多动画,适合移动端。

  • 不同平台下的 QML 使用相同的渲染机制,界面效果一致,不会随操作系统的不同而变化。

但 QML 只能用来进行界面设计和人机交互,也就是只能胜任 UI 部分,在底层仍然需要调用 C++ 编写的组件来完善功能,比如访问数据库、网络通信、多线程多进程、文件读写、图像处理、音频视频处理等都离不开 C++。总的来说,C++ 对于 Qt 是不可或缺的,而 QML只是一个加分项。

1.4QT的下载安装


1.4.1 QT的下载

  • Qt 官方下载(慢)

Qt 官网有一个专门的资源下载网站,所有的开发环境和相关工具都可以从这里下载,具体地址是Index of /

目录说明
archive各种 Qt 开发工具安装包,新旧都有(可以下载 Qt 开发环境和源代码)。
community_releases社区定制的 Qt 库, Tizen 版 Qt 以及 Qt 附加源码包。
development_releases开发版,有新的和旧的不稳定版本,在 Qt 开发过程中的非正式版本。
learning有学习 Qt 的文档教程和示范视频。
ministro迷你版,目前是针对 Android的版本。
official_releases(发布)正式发布版,是与开发版相对的稳定版 Qt 库和开发工具(可以下载 Qt开发环境和源代码)。
onlineQt 在线安装源。
snapshots预览版,最新的开发测试中的 Qt 库和开发工具。

archive 和 official_releases 两个目录都有最新的 Qt开发环境安装包,我们以 archive 目录里的内容为例来说明。点击进入 archive 目录,会看到六个子目录:

目录说明
vsaddin这是 Qt 针对 Visual Studio集成的插件,本教程基本不使用 Visual Studio ,所以不需要插件。
qtcreator这是 Qt 官方的集成开发工具,但是 qtcreator 本身是个空壳,它没有编译套件和 Qt 开发库。除了老版本的 Qt 4 需要手动下载 qtcreator、编译套件、Qt开发库进行搭配之外,一般用不到。 Qt 5 有专门的大安装包,里面包含开发需要的东西,并且能自动配置好。
qt这是 Qt 开发环境的下载目录, Qt 5 的大安装包就在这里面。
online_installers在线安装器,国内用户不建议使用,在线安装是龟速,还经常断线。我们教程采用的全部是离线的大安装包。
designstudioUI设计开发工具相关。
additional_libraries附加库文件

我们再进入 qt 子目录,看到如下列表:

可以看到QT的大版本已经到了6时代,国内有些Qt项目使用了Qt5的版本,甚至是Qt4的版本。本课程将演示Qt5离线、Qt6在线安装的方式。

1.4.2 Linux下的安装

离线安装Qt 5.12

  • 根据你自身的操作系统选择以上离线安装包即可。

QT从5.15版本之后,不再提供离线安装版本,5.15以上版本只能通过在线安装的方式,并且必须通过QT官方网站下载安装器下载安装。

  • 将下载得到的 qt-opensource-linux-x64-5.12.0.run文件拷贝到ubuntu(64bit)的/tmp目录下。通过

cd /tmp 
chmod +x qt-opensource-linux-x64-5.12.0.run sudo
./qt-opensource-linux-x64-5.12.0.run 

下图所示步骤需要输入在QT官网注册的用户名和密码,如果未注册,可以前往Qt Account Login页面完成注册。

安装路径统一选择为/opt/Qt5.12.0

设置选项如下图所示。

  • 安装完毕后,需要修改环境变量PATH

vim ~/.bashrc #文件的最后加入 
export PATH=$PATH:/opt/Qt5.12.0/Tools/QtCreator/bi n:/opt/Qt5.12.0/5.12.0/gcc_64/bin ?#将这两个路径添加带环境变量中去
source ~/.bashrc ? ? ?#使刚刚修改的文件生效

在线安装Qt 6

  • 使用国内镜像下载在线安装工具

  • 在ubuntu环境启动安装工具

cp /mnt/hgfs/swap/qt-unified-linux-x64-4.6.0-online.run  ./ ?#按你自己的方式拿到  ubuntu系统中来 ?
sudo  apt  install ?--reinstall  libxcb-xinerama0 #安装依赖的库 
?
#指定国内镜像源速度会快很多 
sudo ./qt-unified-linux-x64-4.6.0-online.run --mirror https://mirror.nju.edu.cn/qt 

下图所示步骤需要输入在QT官网注册的用户名和密码,如果未注册,可以前往https://login.qt.io/regist er页面完成注册。

下图为组件选择

一路下一步,即可进入安装过程。

为了后续启动qt开发环境方便可以将其对应的路径添加到PATH环境变量

vim ~/.bashrc 
#在文件的最后添加 
export PATH=$PATH:/opt/Qt/6.2.4/gcc_64/bin:/opt/Qt /Tools/QtCreator/bin 
source ~/.bashrc qtcreator 

启动qtcreator时如果出现以下警告

Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run
可以通过修改/etc/gdm3/daemon.conf文件解决 
sudo vim /etc/gdm3/daemon.conf 
WaylandEnable=false #去掉了开头的 # 
sudo reboot 

1.4.3 windows下安装

  • 使用国内镜像下载在线安装工具

  • 进入工具所在目录启动终端

在箭头指向位置输入"cmd",效果如下图所示。

启动在线安装器

qt-unified-windows-x64-4.6.0-online.exe --mirror https://mirror.nju.edu.cn/qt ? #也是指定镜像源

填写用户名密码完成安装过程下图所示步骤需要输入在QT官网注册的用户名和密码,如果未注册,可以前往Qt Account Login页面完成注册。

组件选择如下图所示(注意红色方框中内容的选择,其它保持默认即可)。

其中Additional Libraries的选择如下图所示,(当然土豪磁盘空间够大的话可以把这些附加库都安装上)。

1.5第一个QT程序


启动qtcreator

qtcreator

选择 “文件-->新建文件或项目”,如下图所示

上图窗口左侧有上下两个子窗口,上方的目录树显示了项目内文件的组织结构,显示当前项目为helloworld。项目的名称构成目录树的一个根节点,Qt Creator 可以打开多个项目,但是只有一个活动项目,活动项目的项目名称节点用粗体字体表示。在项目名称节点下面,分组管理着项目内的各种源文件,几个文件及分组分别为以下几项:

  • helloworld.pro 是项目管理文件,包括一些对项目的设置项。

  • Headers 分组,该节点下是项目内的所有头文件(.h),上图中所示项目有一个头文件 mainwindow.h,是主窗口类的头文件.

  • Sources 分组:该节点下是项目内的所有 C++源文件(.cpp),上图中所示项目有两个 C++ 源文件, mainwindow.cpp 是主窗口类的实现文件,与 mainwindow.h 文件对应。main.cpp 是主函数文件,也是应用程序的入口。

  • Forms 分组:该节点下是项目内的所有界面文件(.ui)。上图中所示项目有一个界面文件 mainwindow.ui,是主窗口的界面文件。界面文件是文本文件,使用 XML语言(一种标记语言)描述界面的组成。

双击文件目录树中的文件mainwindow.ui,出现如下图所示的窗体设计界面:设计师模式

这个界面实际上是 Qt Creator 中集成的 Qt Designer。窗口左侧是分组的组件面板,中间是设计的窗体。在组件面板的 Display Widgets 分组里,将一个Label组件拖放到设计的窗体上面。双击刚刚放置的 Label 组件,可以编辑其文字内容,将文字内容更改为“HelloWorld!”。还可以在窗口右下方的属性编辑器里编辑标签的 Font属性,勾选粗体。

出现如下问题

“cannot .nd -lGL” 问题的解决方式

  • 首先需要判断系统中是否安装了libGL

linux@ubuntu:~$ locate libGL #出现以下类似信息说明安装了该库
locate命令, 也是一个文件查找命令
locate命令是基于了数据文件(/var/lib/locatedb)进行的定点查找,由于缩小了搜索范围,因此快速快很多。
原文链接:https://www.linuxcool.com/locate

  • 若判断该库存在,可以通过以下方式解决错误问题

sudo ln -s /usr/lib/x86_64-linux-gnu/mesa/libGL.so.1 /usr/lib/libGL.so
  • 若该库不存在,需要下载安装该库

sudo apt-get install libgl1-mesa-dev

重新编译QT程序,如果报错,需要执行

sudo ln -s /usr/lib/x86_64-linux-gnu/mesa/libGL.so.1 /usr/lib/libGL.so

再次点击qtcreator环境中的,运行效果如下图所示。

qtcreator环境中不能输入中文的问题**

这里建议使用系统(Ubuntu 22.04)自带ibus输入法框架,不要安装搜狗输入法了。

  • 安装中文语言

    在“设置setting”-“区域与语言Region&Language”-“管理已安装的语言Manage Install Languages”-“添加或删除语言Install/Remove Languages”中,安装中文简体

  • 选择ibus框架

    在“设置setting”-“区域与语言Region&Language”-“管理已安装的语言Manage Install Languages”-“键盘输入法系统”中,选择ibus

  • 应用

    点击“应用到整个系统”,然后关闭

  • 安装ibus的pinyin

    sudo apt install ibus-libpinyin

  • 在ibus首选项中添加中文输入法

    ibus-setup 在ibus首选项中,点击“输入法”,添加“中文”-“智能拼音”,然后关闭。

  • reboot

    重启电脑。

    Tips: Qt 官方的开发环境安装包里有自己专门的开发工具,这里将常用的 Qt 开发工具列表如下:

    工具说明
    qmake核心的项目构建工具,可以生成跨平台的 .pro 项目文件,并能依据不同操作系统和编译工具生成相应的 Makefile,用于构建可执行程序或链接库。
    uicUser Interface Compiler,用户界面编译器,Qt 使用 XML 语法格式的 .ui 文件定义用户界面,uic 根据 .ui 文件生成用于创建用户界面的 C++ 代码头文件,比如 ui_*.h 。
    mocMeta-Object Compiler,元对象编译器,moc 处理 C++ 头文件的类定义里面的 Q_OBJECT 宏,它会生成源代码文件,比如 moc_*.cpp ,其中包含相应类的元对象代码,元对象代码主要用于实现 Qt 信号/槽机制、运行时类型定义、动态属性系统。
    rccResource Compiler,资源文件编译器,负责在项目构建过程中编译 .qrc 资源文件,将资源嵌入到最终的 Qt 程序里。
    qtcreator集成开发环境,包含项目生成管理、代码编辑、图形界面可视化编辑、编译生成、程序调试、上下文帮助、版本控制系统集成等众多功能,还支持手机和嵌入式设备的程序生成部署。
    assistantQt 助手,帮助文档浏览查询工具,Qt库所有模块和开发工具的帮助文档、示例代码等都可以检索到,是 Qt 开发必备神器,也可用于自学 Qt。
    designerQt 设计师,专门用于可视化编辑图形用户界面(所见即所得),生成 .ui 文件用于 Qt 项目。
    linguistQt 语言家,代码里用 tr() 宏包裹的就是可翻译的字符串,开发人员可用 lupdate 命令生成项目的待翻译字符串文件 .ts,用 linguist 翻译多国语言 .ts,翻译完成后用 lrelease 命令生成 .qm文件,然后就可用于多国语言界面显示。
    qmlscene在 Qt 4.x 里是用 qmlviewer 进行 QML程序的原型设计和测试,Qt 5 用 qmlscene 取代了旧的 qmlviewer。新的 qmlscene 另外还支持 Qt 5 中的新特性 scenegraph 。

1.6 可视化UI设计


Qt在进行UI界面设计时提供了designer工具,专门用于可视化编辑图形用户界面(所见即所得),该方式效果直观,效率很高。 如图在helloworld项目的基础上,拖动Push Button按钮到布局窗口,并修改文字内容为“退出”。

如下图所示添加对应的信号和槽函数

执行程序,点击退出按钮观察实验效果。

1.7 代码化UI设计


UI的可视化设计时对用户而言的,其实底层都是C++代码实现的,只是QT巧妙地进行了处理,让用户省去了很多繁琐的界面设计工作。由于界面设计的底层都是由 C++语言实现的,底层实现的功能比可视化设计更加强大和灵活。某些界面效果是可视化设计无法完成的,或者某些人习惯了用纯代码的方式来实现设计界面,就可以采用纯代码的方式设计界面,如QT自带的实例基本都是纯代码方式实现用于界面的。

  • 新建工程

去掉“创建界面”的复选框。

修改mainwindow.h为如下代码

#ifndef MAINWINDOW_H 
#define MAINWINDOW_H 
?
#include <QMainWindow> 
#include <QLabel> 
#include <QPushButton> 
class MainWindow : public QMainWindow { 
    Q_OBJECT 
public: 
    MainWindow(QWidget *parent = 0); 
    ~MainWindow(); 
private: 
    QLabel *label1 ; 
    QPushButton *btn1; 
}; 
#endif // MAINWINDOW_H 

修改mainwindow.cpp为如下代码

#include "mainwindow.h" 
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { 
    label1 = new QLabel("HelloWorld!", this);
 ? ?btn1 = new QPushButton("退出 ", this);
 ? ?
 ? ?//setGeometry(x, y, w, h), x, y是相对于按钮依托的那个组件的, 也就是mainwindos的
 ? ?btn1->setGeometry(10,30, 50,50);
 ? ?connect(btn1, SIGNAL(clicked()), this, SLOT(close()));
} 
    MainWindow::~MainWindow() { 
    }
?

编译运行程序,和1.6章节代码实现效果相同。

1.7.1 信号与槽

macros: 宏

[static] QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)
 ? ?
举例: 
QLabel *label = new QLabel; 
QScrollBar *scrollBar = new QScrollBar;
QObject::connect(scrollBar, SIGNAL(valueChanged(int)),label, SLOT(setNum(int)));
?
/*
SIGNAL : 都是Qt里面内置的方法, 帮我们转换为connect函数需要的参数
SLOT
?
*/

需要注意:

  • 信号与槽函数参数要一致

QObject::connect(A,SIGNAL(sigfun(int)), B,SLOT(slotfun(int)));//ok
QObject::connect(A,SIGNAL(sigfun(int)), B,SLOT(slotfun(int,int)));//error
  • 可以带有缺省参数

QObject::connect(A,SIGNAL(sigfun(int)), B,SLOT(slotfun(int,int=0)));//ok 
  • 信号函数的参数可以多于槽函数,多余参数将被忽略

QObject::connect(A,SIGNAL(sigfun(int,int) ), B,SLOT(slotfun(int)));//ok
  • 一个信号可以被连接到多个槽(一对多)

QObject::connect(A,SIGNAL(sigfun(int)), B1,SLOT(slotfun1(int)));//ok
QObject::connect(A,SIGNAL(sigfun(int)), B2,SLOT(slotfun2(int)));//ok
  • 多个信号也可以连接到同一个槽(多对一)

QObject::connect(A1,SIGNAL(sigfun1(int)), B,SLOT(slotfun(int)));//ok
QObject::connect(A2,SIGNAL(sigfun2(int)), B,SLOT(slotfun(int)));//ok
  • 两个信号可以直接连接(信号级联)

QObject::connect(A1,SIGNAL(sigfun1(int)), A2,SIGNAL(sigfun2(int)));//ok

题外话:connect的重载版本

QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection) QMetaObject::Connection 
QObject::connect(const QObject *sender, const QMetaMethod &signal, const QObject *receiver, const QMetaMethod &method, Qt::ConnectionType type = Qt::AutoConnection) QMetaObject::Connection 
QObject::connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type = Qt::AutoConnection) const QMetaObject::Connection 
QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection) QMetaObject::Connection 
QObject::connect(const QObject *sender, PointerToMemberFunction signal, Functor functor) QMetaObject::Connection 
QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection) 

  • connect一(使用最多)

[static] QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)

示例:

QLabel *label = new QLabel; 
QScrollBar *scrollBar = new QScrollBar; 
//指定信号与槽时必须使用 SIGNAL和 SLOT这两个宏帮助我们完成转换
QObject::connect(scrollBar, SIGNAL(valueChanged(int)), label, SLOT(setNum(int))); 
?
//语法错误不能指定形参类型 
QObject::connect(scrollBar, SIGNAL(valueChanged(int value)), label, SLOT(setNum(int value))); 
class MyWidget : public QWidget { 
    Q_OBJECT ? ? ? ? ?//不是c++的语法, 是Qt内置的语法, 会转换成标准的c++语法的, 不用奇怪
public:
 ? ?MyWidget(); 
    signals:
 ? ?void buttonClicked(); 
private: 
 ? ?QPushButton *myButton;
}; 
MyWidget::MyWidget() { 
    myButton = new QPushButton(this); 
    //一个信号也可以连接到另一个信号 
    connect(myButton, SIGNAL(clicked()), this, SIGNAL(buttonClicked())); 
} 

  • connect二

QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMethod &signal, constQObject *receiver, const QMetaMethod &method, Qt::ConnectionType type = Qt::AutoConnection)

示例:

connect(ui->pushButton_2,&QPushButton::clicked,this, &::MainWindow::pushButon2_clicked); 
//若clicked信号有重载版本,则要写成如下形式 
connect(ui->pushButton_2, static_cast<void (QPushButton::*)(bool)> (&QPushButton::clicked), this, SLOT(pushButon2_clicked())); 

  • connect三

QMetaObject::Connection 
QObject::connect(const QObject *sender, 
const char *signal, const char *method, 
Qt::ConnectionType type = 
Qt::AutoConnection) const
?

等价于connect(sender, signal, this, method, type). //方式一

  • connect四

QMetaObject::Connection 
QObject::connect(const QObject *sender, 
PointerToMemberFunction signal, const 
QObject *receiver, 
PointerToMemberFunction method, 
Qt::ConnectionType type = 
Qt::AutoConnection)

示例:

QLabel *label = new QLabel; 
QLineEdit *lineEdit = new QLineEdit; 
QObject::connect(lineEdit, 
&QLineEdit::textChanged, 
label, 
&QLabel::setText); 

  • connect五

QMetaObject::Connection 
QObject::connect(const QObject *sender, 
PointerToMemberFunction signal, Functor 
functor)

示例:

void someFunction(); 
QPushButton *button = new QPushButton; 
QObject::connect(button, 
&QPushButton::clicked, someFunction); 
//也可以使用 lambda表达式 
QByteArray page = ...; 
QTcpSocket *socket = new QTcpSocket; 
socket->connectToHost("qt-project.org", 
80); 
QObject::connect(socket, 
&QTcpSocket::connected, [=] () { 
socket->write("GET " + page + 
"\r\n"); 
}); 

  • connect六

QMetaObject::Connection 
QObject::connect(const QObject *sender, 
PointerToMemberFunction signal, const 
QObject *context, Functor functor, 
Qt::ConnectionType type = 
Qt::AutoConnection) 

示例:

void someFunction(); 
    QPushButton *button = new QPushButton; 
    QObject::connect(button, &QPushButton::clicked, this, someFunction, Qt::QueuedConnection); 

1.7.2 更彻底的代码化UI设计

#include <QApplication> ? ? ? ? ? 
#include <QWidget> 
#include <QLabel> 
?
int main(int argc, char *argv[]) 
{
 ? ?QApplication a(argc, argv); 
 ? ?QWidget w; 
    QLabel label("helloworld", &w); 
    w.resize(140,300);
 ? ?w.move(500,400); 
 ? ?label.move(50,100); 
    w.show(); 
?
 ? ?return a.exec(); ? ? ?//返回等待用户输入的应用程序, 启动一个事件循环, 接收用户的输入
} 
?
qmake -rpoject 生成工程文件, 里面记录着生成makefile的规则, 导入拿些模块等
qmake 根据.pro文件生成makefile
make, 根据makefile里面的内容编译源程序
########################################### ########################### 
# Automatically generated by qmake (3.1) Thu Jul 20 22:26:55 2023 ########################################### ########################### 
?
QT += widgets ? ? ?#编译的规则, 导入相应的模块
TEMPLATE = app
TARGET = 01
INCLUDEPATH += . 
?
# The following define makes your compiler warn you if you use any
# feature of Qt which has been marked as deprecated (the exact warnings 
# depend on your compiler). Please consult the documentation of the 
# deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS 
?
# You can also make your code fail to compile if you use 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.0 
?
# Input
SOURCES += main.cpp

image-20231127152726978

作业:在以上代码的基础上增加退出按钮保证点击按钮时退出应用

image-20231127154457734

解决办法:指明作用域, 带来了二义性问题可能是你编译器不知道调用哪一个函数版本

信号与槽机制是Qobject这个类实现的

1.8 混合方式UI设计


可视化UI设计无需人工编写代码去处理大量繁琐的界面组件的创建和布局管理工作,可以直接进行界面设计,大大提高工作效率。但是可视化UI设计也存在一些缺陷,如某些组件无法可视化添加到界面上,比如在工具栏无法可视化添加ComboBox组件,而用代码就可以。而采用纯代码方式进行UI设计虽然无所不能,但设计效率太低,过程繁琐,而UI设计简单高效。所以,能用可视化UI设计的尽可能用可视化设计解决,无法解决的在用纯代码方式,将两种方式结合,才是高效设计UI的方法。

  • 创建工程

  • UI可视化界面添加QLabel组件

  • 代码添加QPushButton组件

mainwindow.h文件代码如下:

#ifndef MAINWINDOW_H 
#define MAINWINDOW_H 
#include <QMainWindow>
#include <QPushButton> 
namespace Ui {
 ? ?class MainWindow; } 
    class MainWindow : public QMainWindow { 
        Q_OBJECT 
public: 
    explicit MainWindow(QWidget *parent = nullptr); 
    ~MainWindow(); 
private: 
    Ui::MainWindow *ui; 
    QPushButton *btn1; 
}; 
#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);
 ? ?btn1 = new QPushButton("退出 ", this);
 ? ?btn1->setGeometry(100,150, 50,50);
 ? ?connect(btn1, SIGNAL(clicked()), this, SLOT(close())); }    
?
MainWindow::~MainWindow() { 
?
}
?
?
?

编译运行程序,实验效果与1.6、1.7章节代码运行效果相同。

1.9本章常见方法总结

setGeometry(int x, int y, int width, int high) ? ?//设置对象的几何位置, 屏幕的左上角为(0, 0)点.
resize(int width, int high) ? ? ? ? ? ? ? ? ? ? ? //设置组件对象的大小
move(int x, int y) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//设置组件对象的相对位置
?
文章来源:https://blog.csdn.net/m0_74976404/article/details/134699824
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。