《QT 示例宝库:探索丰富的编程世界》
- [一、QT 基础示例](#一、QT 基础示例)
-
- [(一)QRadioButton 示例](#(一)QRadioButton 示例)
- (二)拦截关闭事件示例
- [二、QT 常用代码示例](#二、QT 常用代码示例)
-
- [(一)QObject 相关操作](#(一)QObject 相关操作)
- [(二)Qt 基本容器遍历](#(二)Qt 基本容器遍历)
- (三)数据库操作
- [三、QT 单例模式示例](#三、QT 单例模式示例)
-
- [(一)Qt 单例模式实现方法一](#(一)Qt 单例模式实现方法一)
- [(二)Qt 单例模式实现方法二](#(二)Qt 单例模式实现方法二)
- [四、QT 应用实例](#四、QT 应用实例)
- [五、QT 实用小案例](#五、QT 实用小案例)
- [六、QT 经典例子](#六、QT 经典例子)
-
- [(一)QT 开发的经典软件](#(一)QT 开发的经典软件)
- [(二)MFC 开发案例对比](#(二)MFC 开发案例对比)
- [七、QT 开发实战案例](#七、QT 开发实战案例)
-
- [(一)Qt 框架概述与应用](#(一)Qt 框架概述与应用)
-
- [1. 简介](#1. 简介)
- [2. 历史](#2. 历史)
- [3. 核心价值](#3. 核心价值)
- [4. 应用场景](#4. 应用场景)
- [5. 关键知识点](#5. 关键知识点)
- [(二)Qt 库及其功能](#(二)Qt 库及其功能)
-
- [1. Qt 基础类库](#1. Qt 基础类库)
-
- [(1)Qt 核心类库](#(1)Qt 核心类库)
- [(2)Qt 容器类库](#(2)Qt 容器类库)
- [(3)Qt 工具类库](#(3)Qt 工具类库)
- [2. 图形和图像处理](#2. 图形和图像处理)
- [八、QT 项目开发实例](#八、QT 项目开发实例)
-
- [1、QT 开发环境安装以配置](#1、QT 开发环境安装以配置)
- [2、QT 线段画板实战](#2、QT 线段画板实战)
- [3、QT 入门开发一个时钟](#3、QT 入门开发一个时钟)
- [4、半小时教你做大转盘游戏(QT 篇)](#4、半小时教你做大转盘游戏(QT 篇))
- 5、手把手教你制作【带吸附效果的线段绘制】(QT)
- [6、手把手教你开发 - 滚动效果号码抽奖(QT)](#6、手把手教你开发 - 滚动效果号码抽奖(QT))
- [7、100 行代码实现贪吃蛇小游戏](#7、100 行代码实现贪吃蛇小游戏)
- [8、C++ 实现《扫雷》游戏(入门经典)](#8、C++ 实现《扫雷》游戏(入门经典))
- [9、svg 转图片工具开发](#9、svg 转图片工具开发)
- [10、Qt 网路与通信 (获取本机网络信息)](#10、Qt 网路与通信 (获取本机网络信息))
- [11、Qt 网路与通信 (UDP 客户与服务)](#11、Qt 网路与通信 (UDP 客户与服务))
- [12、Qt 网络与通信(TCP 聊天室)](#12、Qt 网络与通信(TCP 聊天室))
- [13、Qt 多线程以及线程池](#13、Qt 多线程以及线程池)
- 14、取色器(QT)
- [15、MQTT 客户端入门开发](#15、MQTT 客户端入门开发)
- [16、QT 文件上传带进度条实例(含源码)](#16、QT 文件上传带进度条实例(含源码))
- [17、Qt 音乐播放器开发实例(可毕设含源码)](#17、Qt 音乐播放器开发实例(可毕设含源码))
- [九、QT 小案例集合](#九、QT 小案例集合)
- [十、Qt 官方实用例子](#十、Qt 官方实用例子)
-
- [(一)、Qt5.15.2 中的 ChartView 基本使用](#(一)、Qt5.15.2 中的 ChartView 基本使用)
- [(二)、Qt5.15.2 中的模拟示波器](#(二)、Qt5.15.2 中的模拟示波器)
一、QT 基础示例
(一)QRadioButton 示例
QRadioButton 是 Qt 中用于创建单选按钮的类,它提供了丰富的功能和灵活的样式设置选项。以下将展示使用 QRadioButton 创建单选按钮组的代码示例,包括按钮的创建、添加到按钮组以及布局设置。
-
创建 QRadioButton
在 Qt 中,可以使用 QRadioButton 的构造函数来创建单选按钮。例如:QRadioButton *button1 = new QRadioButton("选项 1", this);
QRadioButton *button2 = new QRadioButton("选项 2", this);
QRadioButton *button3 = new QRadioButton("选项 3", this);
这里创建了三个单选按钮,分别命名为 "选项 1"、"选项 2" 和 "选项 3"。
- 添加到按钮组
为了实现单选按钮的互斥功能,可以将它们添加到一个按钮组中。在 Qt 中,可以使用 QButtonGroup 类来创建按钮组。例如:
QButtonGroup *buttonGroup = new QButtonGroup(this);
buttonGroup->addButton(button1);
buttonGroup->addButton(button2);
buttonGroup->addButton(button3);
这样,当用户选择其中一个单选按钮时,其他单选按钮将自动取消选择。
- 设置布局
为了将单选按钮和其他控件显示在窗口中,需要设置布局。在 Qt 中,可以使用 QVBoxLayout、QHBoxLayout 等布局类来实现不同的布局效果。例如:
QVBoxLayout *layout = new QVBoxLayout();
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
setLayout(layout);
这里创建了一个垂直布局,并将三个单选按钮添加到布局中。最后,将布局设置为窗口的布局,这样单选按钮就会显示在窗口中。
- 自定义样式
Qt 允许通过样式表来自定义 QRadioButton 的外观。例如,可以设置单选按钮的图标、颜色、大小等。以下是一个自定义 QRadioButton 样式的示例:
QRadioButton::indicator::unchecked {
border-image: url(images/user_protocol_uncheck.webp);
}
QRadioButton::indicator::checked {
border-image: url(images/user_protocol_checked.webp);
}
QRadioButton::indicator {
width: 24px;
height: 24px;
}
在这个示例中,使用了 border-image 属性来设置单选按钮的未选中和选中状态的图标。可以根据自己的需求修改图标路径和大小。
- Python 中的 QRadioButton
在 Python 中,可以使用 PyQt5 库来创建 QRadioButton。以下是一个使用 Python 和 Qt 实现 QRadioButton 的步骤指南:
安装 PyQt5 库:在命令行中运行 pip install PyQt5 来安装 PyQt5 库。
创建主窗口:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QRadioButton, QLabel
app = QApplication(sys.argv)
main_window = QWidget()
main_window.setWindowTitle('QRadioButton 示例')
main_window.setGeometry(100, 100, 300, 200)
这里创建了一个 Qt 应用程序和一个主窗口,并设置了窗口的标题和尺寸。
添加 QRadioButton:
layout = QVBoxLayout()
radio1 = QRadioButton('选项 1')
radio2 = QRadioButton('选项 2')
radio3 = QRadioButton('选项 3')
layout.addWidget(radio1)
layout.addWidget(radio2)
layout.addWidget(radio3)
这里创建了三个单选按钮,并将它们添加到一个垂直布局中。
设置信号与槽连接:
label = QLabel('请选择一个选项')
def radio_button_selected():
selected_option = '选中: '
if radio1.isChecked():
selected_option += '选项 1'
elif radio2.isChecked():
selected_option += '选项 2'
elif radio3.isChecked():
selected_option += '选项 3'
label.setText(selected_option)
radio1.toggled.connect(radio_button_selected)
radio2.toggled.connect(radio_button_selected)
radio3.toggled.connect(radio_button_selected)
layout.addWidget(label)
这里创建了一个标签来显示当前选择的单选按钮,并定义了一个函数 radio_button_selected,根据用户选择的按钮更新标签的文本。然后,将单选按钮的 toggled 信号连接到这个函数。
显示窗口并运行程序:
main_window.setLayout(layout)
main_window.show()
sys.exit(app.exec_())
这里将布局设置到主窗口,并显示窗口。最后,运行应用程序的事件循环。
(二)拦截关闭事件示例
在 Qt 中,可以通过实现 closeEvent 函数来拦截关闭窗口消息,从而在程序有任务运行时弹出警告窗口,由用户决定是否退出。
-
实现 closeEvent 函数
在 Qt 中,closeEvent 函数是一个虚函数,用于处理窗口关闭事件。可以在自定义的窗口类中重写这个函数,以实现拦截关闭事件的功能。例如:void MainWindow::closeEvent(QCloseEvent *event)
{
if (hasRunningTasks()) {
QMessageBox::StandardButton result = QMessageBox::question(this, tr("提示"), tr("程序有任务正在运行,确定要退出吗?"), QMessageBox::Yes | QMessageBox::No);
if (result == QMessageBox::Yes) {
event->accept();
} else {
event->ignore();
}
} else {
event->accept();
}
}
在这个示例中,首先检查是否有任务正在运行。如果有任务正在运行,弹出一个警告窗口,询问用户是否确定退出。如果用户选择 "是",则接受关闭事件;如果用户选择 "否",则忽略关闭事件。如果没有任务正在运行,则直接接受关闭事件。
- 检查任务状态
在上面的示例中,hasRunningTasks 函数用于检查是否有任务正在运行。这个函数可以根据实际情况进行实现。例如,可以检查是否有正在进行的网络请求、文件读写操作等。以下是一个简单的示例:
bool MainWindow::hasRunningTasks()
{
return false;
}
在这个示例中,直接返回 false,表示没有任务正在运行。在实际应用中,可以根据具体情况进行修改。
- 效果展示
当程序有任务正在运行时,点击窗口的关闭按钮,会弹出一个警告窗口,询问用户是否确定退出。如果用户选择 "是",则程序退出;如果用户选择 "否",则窗口保持打开状态。
通过拦截关闭事件,可以在程序有任务运行时提醒用户,避免数据丢失或其他意外情况的发生。同时,也可以根据需要在关闭事件中执行一些清理操作,如保存数据、释放资源等。
二、QT 常用代码示例
(一)QObject 相关操作
简述:介绍了 QObject 的一些常用操作,如类型转化、查找子类、事件过滤、注册函数到原对象系统等。
QObject 是 Qt 所有对象的基类,提供了强大的功能机制。其中包括信号和槽的机制,可使用 connect () 方法连接信号和槽,用 disconnect () 方法断开连接。QObjects 用对象树来组织自身,当创建一个 QObject 并将另一个对象设为其 parent 时,该对象会自动加入到 parent 的 children 列表中,parent 拥有对象的所有权。
可以使用 findChild () 方法或 findChildren () 方法查找一个对象或对象列表,每个对象都有对象名称(objectName ()),其类名可通过 metaObject () 得到。
Qt 中还可以利用 QObject 类实现定时器功能。通过 QObject::startTimer () 开启定时器,以毫秒为单位设置时间间隔,返回唯一的整数定时器标识符。定时器开启后,每隔指定时间间隔触发超时事件,直到调用 QObject::killTimer () 结束定时器。当定时器触发时,应用程序会发送一个 QTimerEvent。在事件循环中,处理器按事件队列顺序处理定时器事件。当处理器忙于其他事件处理时,定时器不能立即处理。
以下是一个利用 QObject 类实现定时器功能的示例:
widget.h 头文件中声明 timerEvent 函数和 id 变量:
protected:
void timerEvent(QTimerEvent *event);
int m_nTimerId;
widget.cpp 源文件中,在构造函数中设置每隔 1000ms 响应一次:
m_nTimerId = startTimer(1000);
在析构函数中将其析构掉:
Widget::~Widget() {
if (m_nTimerId!= 0)
killTimer(m_nTimerId);
}
在 timerEvent 函数中设置每隔时间相应的内容:
void Widget::timerEvent(QTimerEvent *event) {
qDebug("timer event, id %d", event->timerId());
}
此外,在 Qt 中,当某一个 Object emit 一个 signal 的时候,它就是一个 sender,系统会记录下当前是谁 emit 出这个 signal 的,在对应的 slot 里可以通过 sender () 得到当前是谁 invoke 了你的 slot,对应的是 QObject->ed->sender。有可能多个 Object 的 signal 会连接到同一个 slot(例如多个 Button 可能会 connect 到一个 slot 函数),此时就需要判断到底是哪个 Object emit 了这个 signal,根据 sender 的不同进行不同的处理。
示例代码:
QTimeEdit *editor = qobject_cast<QTimeEdit *>(sender());
// 此时可以对 editor 进行进一步的处理了。
QPushButton *aaaa = new QPushButton(this);
connect(aaaaa, SIGNAL(Click()), this, SLOT(Onaaaaa()));
void Onaaaaa() {
QPushButton *ccc = (QPushButton*)sender();
}
(二)Qt 基本容器遍历
简述:展示了 Qt 基本容器(如 QList、QMap 等)的不同遍历方式,包括 JAVA 风格遍历、迭代器遍历、反向迭代和 foreach 迭代等。
Qt 提供了一组通用的基于模板的容器类,相比 C++ 标准模板库,Qt 的容器更轻量安全且更容易使用,同时在速度、内存消耗和内联代码等方面进行了优化。Qt 容器可存储的必须是可赋值的数据类型,包括基本数据类型和 Qt 的一些数据类型(如 QString)等,但 Qt 的 QObject 及其子类(如 QWidget)等不能存储在容器中,可以通过指针存储。Qt 的容器类也支持嵌套。
Qt 容器的两种遍历方式有 JAVA 型和 STL 型,推荐使用 STL(通用且效率高)。
QList 类
QList 是最常用的容器之一,维护了一个指针数组,支持基于下标的快速访问。根据存储的数据类型不同,QList 会采取不同的存储策略。
示例代码:
QList<QString> list;
QString str("This is a test string");
list << str;
qDebug() << list[0] << "How are you!";
QLinkedList 类
QLinkedList 是链式列表,以非连续的内存块保存数据,不能使用下标,只能使用迭代器。在对大列表进行插入操作时,QLinkedList 效率更高。
QVector 类
QVector 在相邻内存中存储给定类型的一组数值,在其前部或中间位置进行插入操作速度较慢,因为会导致大量数据移动。QVector 既可以通过下标访问,也可以通过迭代器访问。
Java 风格迭代器遍历
相比 STL 风格迭代器遍历,JAVA 更方便,但性能消耗较大。对于每个容器类,Qt 都提供两种 Java 风格迭代器数据类型,即只读访问和读写访问。
示例代码:
QList<int> list;
list << 1 << 2 << 3 << 4 << 5;
QListIterator<int> it(list);
for (; it.hasNext();)
qDebug() << it.next();
STL 风格迭代器
STL 风格迭代器的 API 是建立在指针操作基础上的,比如 ++ 可以移动到下一项,而 * 可以拿到迭代器指向的值。
示例代码:
QList<double>::iterator i = list.begin();
while (i!= list.end()) {
*i = qAbs(*i);
++i;
}
foreach 迭代
Qt 提供了一种不使用遍历器进行遍历的方法:foreach 循环。
示例代码:
QLinkedList<Movie> list;
Movie movie;
...
foreach (movie, list) {
if (movie.title() == "Citizen Kane") {
std::cout << "Found Citizen Kane" << std::endl;
break;
}
}
Qt 还提供了关联存储容器 QMap 和 QHash。QMap 是一种键 - 值对的数据结构,按照键进行升序存储。可以使用 insert () 函数或重载的 [] 运算符向 QMap 中插入数据。
遍历关联存储容器的最简单办法是使用 Java 风格的遍历器,因为 Java 风格的遍历器的 next () 和 previous () 函数可以返回一个键 - 值对,也可以直接调用 key () 和 value () 函数获取键和值。Mutable 遍历器则可以修改 key 对应的值。
如果是 STL 风格的遍历器,则可以使用它的 key () 和 value () 函数。对于 foreach 循环,需要分别对 key 和 value 进行循环。
(三)数据库操作
简述:演示了使用 Qt 连接数据库、执行 SQL 语句、查询表以及设置 tableView 模型和显示头的方法。
Qt 中的 QtSQL 模块提供了对数据库的支持,该模块中的众多类基本上分为三类:用户接口层、SQL 接口层、驱动层。
添加 SQL 数据库驱动
Qt 默认支持一些驱动,也可以添加其他驱动。可以使用 QSqlDatabase 类的静态函数 drivers () 来获取可用的驱动列表。
示例代码:
QApplication a(argc, argv);
qDebug() << "Available drivers:";
QStringList drivers = QSqlDatabase::drivers();
foreach (QString driver, drivers)
qDebug() << driver;
创建数据库连接
创建并打开一个或多个数据库连接,数据库连接使用连接名定义。可以使用 QSqlDatabase 类的 addDatabase () 方法创建连接对象,设置数据库名称并使用 open () 方法打开连接。如果连接失败,会弹出提示对话框。
示例代码:
static bool createConnection() {
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":memory:");
if (!db.open()) {
QMessageBox::critical(0, "Cannot open database", "Unable to establish a database connection.", QMessageBox::Cancel);
return false;
}
QSqlQuery query;
query.exec("create table student(id int primary key, name varchar(20))");
query.exec("insert into student values(0,'LiMing')");
query.exec("insert into student values(1,'LiuTao')");
query.exec("insert into student values(2,'WangHong')");
return true;
}
创建多个连接
可以同时建立多个连接,但不同的连接要有不同的连接名。
(四)HTTP 请求
简述:说明了如何使用 QNetworkAccessManager 发送 HTTP 请求,并处理请求结果和错误。
可以使用 QNetworkAccessManager 类发送 HTTP 请求,使用 QNetworkRequest 类包含请求信息,使用 QNetworkReply 类包含接收到的数据部分和请求头部。
示例代码:
// 发送 http 请求
void MainWindow::requestFail(QString str) {
qDebug() << "----------requestFail-------------";
qDebug() << str;
}
void MainWindow::requestSuccess(QString str) {
qDebug() << "----------requestSuccess-------------";
qDebug() << str;
}
void MainWindow::onSendHttpsRequest(QString url) {
QNetworkAccessManager* pManager = new QNetworkAccessManager(this);
QNetworkRequest request;
// 发送 https 请求前准备工作;
QSslConfiguration config;
QSslConfiguration conf = request.sslConfiguration();
conf.setPeerVerifyMode(QSslSocket::VerifyNone);
conf.setProtocol(QSsl::TlsV1SslV3);
request.setSslConfiguration(conf);
request.setUrl(QUrl(url));
QNetworkReply *pReply = pManager->post(request, bytePost);
connect(pReply, SIGNAL(finished()), this, SLOT(onFinished()));
connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onError(QNetworkReply::NetworkError)));
}
// 请求完成;
void MainWindow::onFinished() {
QNetworkReply *pReplay = qobject_cast<QNetworkReply*>(sender());
// 保存接受的数据;
QByteArray replyContent = pReplay->readAll();
}
// 请求失败;
void MainWindow::onError(QNetworkReply::NetworkError errorCode) {
QNetworkReply *pReplay = qobject_cast<QNetworkReply*>(sender());
// 输出错误码及错误信息;
qDebug() << errorCode;
qDebug() << pReplay->errorString();
}
三、QT 单例模式示例
简述:给出了两种使用 Qt 实现单例模式的方法,并通过代码示例进行了详细讲解。
(一)Qt 单例模式实现方法一
Qt 中可以通过模板类的方式实现单例模式,以下是具体的实现步骤和代码示例:
定义模板类
template <class T>
class Singleton
{
public:
static T& instance()
{
static QMutex mutex;
static QScopedPointer<T> inst;
if (Q_UNLIKELY(!inst)) {
mutex.lock();
if (!inst) {
inst.reset(new T);
}
mutex.unlock();
}
return *inst;
}
private:
Singleton() {}
~Singleton() {}
Q_DISABLE_COPY(Singleton);
};
使用示例
假设我们有一个名为 MyClass 的类,想要实现单例模式,可以这样使用上述模板类:
class MyClass
{
// 限制构造函数为私有,确保只能通过单例模式获取实例
private:
MyClass() {}
~MyClass() {}
Q_DISABLE_COPY(MyClass);
public:
// 声明单例模式
friend class Singleton<MyClass>;
// 可以添加其他成员函数和变量
};
int main()
{
MyClass& instance = Singleton<MyClass>::instance();
// 使用实例
return 0;
}
(二)Qt 单例模式实现方法二
还可以通过宏定义的方式实现单例模式,以下是具体的实现和示例:
定义宏
#define DECLARE_SINGLETON(Class) \\
Q_DISABLE_COPY(Class) \\
public: \\
static Class* Instance() \\
{ \\
static QMutex mutex; \\
static QScopedPointer<Class> inst; \\
if (Q_UNLIKELY(!inst)) { \\
mutex.lock(); \\
if (!inst) inst.reset(new Class); \\
mutex.unlock(); \\
} \\
return inst.data(); \\
}
使用示例
对于一个名为 OtherClass 的类,可以这样声明单例模式:
class OtherClass
{
// 限制构造函数为私有,确保只能通过单例模式获取实例
private:
OtherClass() {}
~OtherClass() {}
Q_DISABLE_COPY(OtherClass);
public:
// 声明单例模式
DECLARE_SINGLETON(OtherClass);
// 可以添加其他成员函数和变量
};
int main()
{
OtherClass* instance = OtherClass::Instance();
// 使用实例
return 0;
}
四、QT 应用实例
(一)跨平台性优势
Qt 作为一款强大的 C++ 应用程序开发框架,其跨平台性能是众多开发者青睐的重要特性之一。Qt 能够在不同操作系统下快速开发应用程序,极大地提高了开发效率。
Qt 的跨平台性意味着开发者只需编写一次代码,就可以在多个操作系统上运行,包括 Windows、MacOS、Linux 等。这种一次编译多平台运行的特性,大大节省了开发人员的时间成本。例如,一个使用 Qt 开发的软件,在 Windows 上开发完成后,无需进行大规模的代码修改,就可以轻松地移植到 MacOS 或 Linux 系统上。
Qt 的跨平台性能不仅体现在桌面操作系统上,还可以应用于移动平台和嵌入式系统。这使得开发者可以针对不同的平台需求,快速开发出适应各种环境的应用程序。无论是在智能手机、平板电脑还是嵌入式设备上,Qt 都能提供一致的开发体验和稳定的性能表现。
总之,Qt 的跨平台性能为开发者提供了极大的便利,使得他们能够更加高效地开发出适用于不同操作系统的应用程序。
(二)丰富功能库应用
Qt 拥有丰富的功能库,在软件开发中发挥着重要作用。这些功能库涵盖了 GUI 开发、网络通讯、数据库操作等多个方面,为开发者提供了强大的工具和资源。
在 GUI 开发方面,Qt 提供了丰富的图形界面组件,如按钮、文本框、列表框、图表等。开发者可以通过可视化的设计工具进行拖拽和布局,快速创建出美观的用户界面。同时,Qt 还支持自定义样式,开发者可以根据自己的需求设置界面的外观和风格。
网络通讯方面,Qt 提供了一系列的类和函数,用于实现网络编程。开发者可以轻松地实现客户端和服务器之间的通信,支持多种网络协议,如 TCP/IP、UDP 等。此外,Qt 还提供了网络安全方面的支持,如 SSL/TLS 加密等。
数据库操作方面,Qt 的 QtSQL 模块提供了对数据库的支持。开发者可以使用该模块连接不同类型的数据库,执行 SQL 语句,进行查询和更新操作。Qt 还提供了数据库模型和视图的支持,使得开发者可以方便地将数据库中的数据显示在用户界面上。
除了上述几个方面,Qt 的功能库还包括图形处理、多媒体处理、多线程编程等。这些功能库使得开发者能够快速构建出功能强大、性能稳定的应用程序,无需从头编写大量底层代码。
(三)开发效率优势
使用 Qt 可以以更少的代码量实现更多功能,从而减少开发周期和维护成本。
Qt 提供了丰富的工具和组件,使得开发人员能够快速生成交互式的、现代化的用户界面。例如,通过 Qt 的可视化设计工具,开发者可以轻松地创建和布局用户界面,无需手动编写大量的界面代码。同时,Qt 的信号与槽机制使得组件之间的交互变得简单而高效,开发者只需连接相应的信号和槽,就可以实现复杂的交互逻辑,而无需编写繁琐的事件处理代码。
Qt 的跨平台性也为开发效率带来了很大的提升。开发者只需编写一次代码,就可以在不同的操作系统上运行,避免了在不同平台上针对性的重新开发。这不仅节省了开发时间,还降低了维护成本。因为一旦代码在一个平台上经过测试和优化,就可以很容易地移植到其他平台上,无需进行大规模的修改。
此外,Qt 拥有庞大的开发者社区和完善的技术支持体系。开发者可以在社区中获取到丰富的开发资源、技术文档和问题解决方案。这为开发者提供了学习、交流和问题求助的平台,也使得 Qt 在技术更新、bug 修复等方面能够快速响应和迭代。
(四)社区支持优势
Qt 庞大的开发者社区和完善的技术支持体系为开发者提供了丰富的资源和问题解决方案。
Qt 社区由众多的开发者组成,他们在社区中分享经验、交流技术、提供代码示例和解决方案。开发者可以在社区中获取到最新的技术动态、学习最佳实践、解决遇到的问题。社区中还提供了丰富的文档和教程,帮助新手快速上手 Qt 开发。
Qt 的技术支持体系也非常完善。Qt 官方提供了详细的文档、示例代码和在线论坛,开发者可以在这些平台上获取到官方的技术支持。此外,还有很多第三方的技术博客、论坛和培训机构,为开发者提供了更多的学习资源和问题解决方案。
社区支持不仅为开发者提供了学习和交流的平台,还促进了 Qt 的不断发展和完善。开发者可以通过社区反馈问题和建议,推动 Qt 在功能、性能和易用性等方面的不断改进。同时,社区中的开源项目和代码贡献也为 Qt 的生态系统增添了丰富的内容。
(五)应用实例列举
Qt 在软件开发领域有着广泛的应用,以下是一些使用 Qt 开发的软件实例:
软件开发工具:Qt Creator 是一款基于 Qt 开发的跨平台集成开发环境,被广泛应用于 C++、QML 和 JavaScript 等多种语言的开发。它提供了丰富的功能,包括代码编辑、调试、项目管理等,为开发者提供了高效的开发工具。
嵌入式设备:由于其跨平台性和高效性能,Qt 被广泛应用于嵌入式设备的软件开发。例如,智能家居设备、嵌入式工业控制系统等领域。Qt 可以为这些设备提供美观的用户界面和强大的功能支持。
跨平台应用程序:许多跨平台应用程序都选择使用 Qt 来实现一次开发多平台运行的目标。其中著名的示例包括 Skype、VLC 媒体播放器等。这些应用程序在不同的操作系统上都能提供一致的用户体验和功能。
此外,还有很多其他使用 Qt 开发的软件,如 3DSlicer(用于可视化和医学图像计算的免费开源软件)、AcetoneISO(镜像文件挂载软件)、Arora(跨平台的开源网页浏览器)等。这些软件涵盖了各个领域,充分展示了 Qt 的广泛应用和强大功能。
五、QT 实用小案例
(一)登录界面
QT 的登录界面可以通过以 Dialog 为基类,并添加 MainWindow 类作为主界面来实现登录功能。以下是具体的实现步骤:
-
创建界面
使用 Qt Creator 创建一个基于 Dialog 的项目,并添加一个 MainWindow 类。在 Dialog 类中,可以使用 Qt 的界面设计器来设计登录界面,包括输入用户名和密码的文本框、登录按钮和取消按钮等。 -
输入验证
在登录按钮的点击事件中,可以对用户输入的用户名和密码进行验证。例如,可以检查用户名和密码是否为空,或者是否与预设的用户名和密码匹配。如果验证通过,则可以调用 accept () 函数关闭登录对话框,并显示主界面;如果验证失败,则可以显示错误消息,提示用户重新输入。 -
界面切换
当登录验证通过后,可以使用 show () 函数显示主界面。在主界面的构造函数中,可以接收登录对话框的指针,以便在需要时可以访问登录对话框的成员变量或函数。
以下是一个简单的登录界面的代码示例:#include "dialog.h"
#include "ui_dialog.h"
#include "mainwindow.h"
#include "QMessageBox"Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
}Dialog::~Dialog()
{
delete ui;
}void Dialog::on_pushButton_clicked()
{
if(ui->lineEdit->text().trimmed()=="abc123" && ui->lineEdit_2->text().trimmed()=="123")
{
accept();
}
else
{
QMessageBox::question(this,tr("警告"),tr("用户名或密码错误!!!"),QMessageBox::Yes,QMessageBox::No);
}
}void Dialog::on_pushButton_2_clicked()
{
close();
}
在主窗口的构造函数中,可以接收登录对话框的指针,并在登录成功后显示主窗口:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
(二)菜单和工具栏
在 Qt 中,可以在 MainWindow 中添加菜单和子菜单,并设置快捷键和图标。以下是具体的实现步骤:
-
添加菜单和子菜单
在 Qt Creator 的界面设计器中,可以双击 MainWindow 窗口,然后在属性编辑器中找到 "menuBar" 属性,点击旁边的 "..." 按钮,打开菜单编辑器。在菜单编辑器中,可以添加菜单和子菜单,并设置菜单的名称和快捷键。例如,可以添加一个 "文件" 菜单,并在 "文件" 菜单下添加一个 "打开" 子菜单,设置快捷键为 "Ctrl+O"。 -
设置图标
可以为菜单和子菜单设置图标,以增加用户界面的美观性。在菜单编辑器中,可以选择一个菜单或子菜单,然后在属性编辑器中找到 "icon" 属性,点击旁边的 "..." 按钮,选择一个图标文件。 -
添加动作
可以为菜单和子菜单添加动作,以实现具体的功能。在菜单编辑器中,可以选择一个菜单或子菜单,然后点击 "添加动作" 按钮,创建一个新的动作。可以为动作设置名称、快捷键、图标和槽函数等。例如,可以为 "打开" 子菜单添加一个动作,设置名称为 "打开文件",快捷键为 "Ctrl+O",图标为一个打开的文件夹图标,并在槽函数中实现打开文件的功能。
以下是一个简单的菜单和工具栏的代码示例:#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);// 创建菜单栏 QMenuBar *menuBar = this->menuBar(); QMenu *fileMenu = menuBar->addMenu("&File"); // 创建动作 QAction *openAction = new QAction(QIcon(":/icons/open.png"), "&Open", this); openAction->setShortcut(QKeySequence("Ctrl+O")); fileMenu->addAction(openAction); // 创建工具栏 QToolBar *toolBar = addToolBar("File"); toolBar->addAction(openAction);
}
MainWindow::~MainWindow()
{
delete ui;
}
(三)键盘事件和鼠标事件
在 Qt 中,可以通过设置键盘快捷键切换窗口,以及通过鼠标左键点击改变窗口大小的功能实现。以下是具体的实现步骤:
-
键盘快捷键切换窗口
在 Qt Creator 的界面设计器中,可以选择一个窗口,然后在属性编辑器中找到 "shortcut" 属性,点击旁边的 "..." 按钮,打开快捷键编辑器。在快捷键编辑器中,可以设置一个键盘快捷键,当用户按下这个快捷键时,会触发相应的槽函数。例如,可以设置一个 "Ctrl+N" 的快捷键,当用户按下这个快捷键时,会显示一个新的窗口。
以下是一个简单的键盘快捷键切换窗口的代码示例:#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "widget.h"MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}MainWindow::~MainWindow()
{
delete ui;
}void MainWindow::keyPressEvent(QKeyEvent *event)
{
if(event->modifiers()==Qt::ControlModifier)
{
if(event->key()==Qt::Key_N)
{
Widget *w1=new Widget(this);
w1->show();
}
}
} -
鼠标左键点击改变窗口大小
在 Qt Creator 的界面设计器中,可以选择一个窗口,然后在属性编辑器中找到 "mousePressEvent" 属性,点击旁边的 "..." 按钮,打开事件编辑器。在事件编辑器中,可以选择 "mousePressEvent" 事件,并在相应的槽函数中实现鼠标左键点击改变窗口大小的功能。例如,可以在槽函数中判断窗口的当前状态,如果窗口不是全屏状态,则将窗口设置为全屏状态;如果窗口是全屏状态,则将窗口设置为非全屏状态。
以下是一个简单的鼠标左键点击改变窗口大小的代码示例:#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}MainWindow::~MainWindow()
{
delete ui;
}void MainWindow::mousePressEvent(QMouseEvent *event)
{
if(event->button()==Qt::LeftButton)
{
if(windowState()!=Qt::WindowFullScreen)
setWindowState(Qt::WindowFullScreen);
else
setWindowState(Qt::WindowNoState);
}
}
(四)事件过滤(鼠标键)
在 Qt 中,可以在 widget 中添加事件过滤器,实现对 textEdit 的滚轮事件、spinBox 的按键事件和 label 的鼠标点击事件的处理。以下是具体的实现步骤:
-
安装事件过滤器
在 widget 的构造函数中,可以使用 installEventFilter () 函数为 textEdit、spinBox 和 label 安装事件过滤器。例如:ui->textEdit->installEventFilter(this);
ui->spinBox->installEventFilter(this);
ui->label->installEventFilter(this); -
实现事件过滤器函数
在 widget 类中,可以实现 eventFilter () 函数,用于处理事件过滤器安装的对象的事件。例如:bool Widget::eventFilter(QObject *watched, QEvent *event)
{
if(watched==ui->textEdit)
{
if(event->type()==QEvent::Wheel)
{
QWheelEvent wheelEvent = (QWheelEvent)event;
if(wheelEvent->delta()>0)
ui->textEdit->zoomIn();
else
ui->textEdit->zoomOut();
}
}
else if(watched==ui->spinBox)
{
if(event->type()==QEvent::KeyPress)
{
QKeyEvent keyEvent = (QKeyEvent)event;
if(keyEvent->key()==Qt::Key_Space)
ui->spinBox->setValue(0);
}
}
else if(watched==ui->label)
{
if(event->type()==QEvent::MouseButtonPress)
{
QMouseEvent mouseEvent = (QMouseEvent)event;
if(mouseEvent->button()==Qt::LeftButton)
ui->textEdit->setText(tr("左击了图片!"));
else if(mouseEvent->button()==Qt::RightButton)
ui->textEdit->setText(tr("右击了图片!"));
}
}
else
return QWidget::eventFilter(watched,event);return false;
}
(五)设置不规则窗体(透明度)
在 Qt 中,可以新建 Qt Widget 应用,加载背景透明的 png 图片,设置不规则窗体和透明度。以下是具体的实现步骤:
-
新建 Qt Widget 应用
在 Qt Creator 中,选择 "新建项目"->"Qt Widgets Application",创建一个新的 Qt Widget 应用项目。 -
加载背景透明的 png 图片
将背景透明的 png 图片添加到项目的资源文件中。在 widget 的构造函数中,可以使用 QPixmap 类加载图片,并设置窗口的大小和屏蔽罩。例如:QPixmap pix;
pix.load(":/images/transparent.png");
resize(pix.size());
setMask(pix.mask()); -
设置不规则窗体和透明度
在 widget 的 paintEvent () 函数中,可以使用 QPainter 类绘制图片,并设置窗口的透明度。例如:void Widget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.drawPixmap(0,0,QPixmap(":/images/transparent.png"));
setWindowOpacity(0.5);
}
六、QT 经典例子
(一)QT 开发的经典软件
Qt 作为一款强大的跨平台应用程序开发框架,被广泛应用于众多知名软件的开发中。以下将介绍一些使用 Qt 开发的经典软件。
- 3DSlicer
3DSlicer 是一款用于可视化和医学图像计算的免费开源软件。它在医学影像领域有着广泛的应用,为医生和研究人员提供了强大的图像分析和处理工具。3DSlicer 的界面友好,功能强大,其开发过程中充分利用了 Qt 的跨平台特性和丰富的图形界面功能。 - Skype
Skype 是一个使用人数众多的基于 P2P 的 VOIP 聊天软件。它以其高质量的语音通话和视频通话功能而受到用户的喜爱。Skype 的开发团队选择 Qt 作为开发框架,使得 Skype 能够在多个操作系统上运行,为用户提供了一致的使用体验。 - VLC 多媒体播放器
VLC 多媒体播放器是一个体积小巧、功能强大的开源媒体播放器。它支持多种音频和视频格式,能够播放本地文件和网络流媒体。VLC 的开发过程中使用了 Qt 框架,使得它能够在不同的操作系统上快速开发和部署,同时保持了良好的用户界面和性能。
这些软件只是 Qt 开发的众多经典软件中的一部分,它们的成功充分展示了 Qt 在跨平台应用程序开发中的强大实力。
(二)MFC 开发案例对比
Qt 和 MFC(微软基础类库)都是常用的应用程序开发框架,但它们在很多方面存在差异。
- 跨平台支持
Qt 是一个跨平台的框架,可以在 Windows、Mac OS X、Linux 等多个操作系统上进行应用程序开发。而 MFC 是专门为 Windows 设计的类库,只能在 Windows 平台上使用。 - 设计理念
Qt 的架构明显是经过精心设计的面向对象的,在命名、继承、类的组织等方面保持了优秀的一致性。Qt 中的信号槽机制是对象间建立联系的核心机制,功能强大且易于理解和使用。而 MFC 或多或少使用了面向对象的方法包装了 Win32 的 API,在很多地方存在不连贯和难以理解的问题。 - 文档和帮助
Qt 的帮助文档齐全,主题明确,关键信息突出,链接设计良好,方便用户查找和使用。而 MFC 的帮助文档虽然庞大,但存在泥沙俱下、主题模糊、关键信息不突出的问题,链接设计也很糟糕。 - 创建界面
在 Qt 中,可以使用简单的代码创建大小动态可变的子窗口,并且 Qt 提供了强大的布局机制和图形用户工具 Qt Designer,方便用户创建和修改用户界面。而在 MFC 中,创建大小动态可变的子窗口比较困难,并且在软件进行国际化翻译时需要手动修改大量代码。
综上所述,Qt 在跨平台支持、设计理念、文档和帮助、创建界面等方面都具有明显的优势,而 MFC 则在 Windows 平台上具有较高的效率。开发人员可以根据自己的需求和项目特点选择合适的开发框架。
七、QT 开发实战案例
(一)Qt 框架概述与应用
Qt 是一个强大的跨平台应用程序开发框架,自 1991 年诞生以来,历经多次公司收购,目前在应用程序开发领域占据重要地位。
1. 简介
Qt 是一个跨平台的 C++ 应用程序框架,支持多种操作系统,包括 Windows、Linux、Mac OS X、Android、iOS 等。它提供了丰富的类库和工具,用于开发图形用户界面(GUI)应用程序、网络应用程序、数据库应用程序等。
2. 历史
Qt 由奇趣科技公司(Trolltech)的两位创始人于 1990 年着手开发,1995 年发布 Qt 1.0。2008 年,奇趣科技被诺基亚公司收购,Qt 也因此成为诺基亚旗下的编程语言工具。2012 年,诺基亚将 Qt 转让给 Digia 公司。目前,Qt 由一家中国公司持有。
3. 核心价值
(1)跨平台性:Qt 可以在不同的操作系统上运行,开发者只需编写一次代码,就可以在多个平台上编译运行,极大地提高了开发效率和应用的普及度。
(2)组件化设计:Qt 提供了丰富的组件和工具,开发者可以根据自己的需求选择合适的组件进行开发,提高了开发的灵活性和可维护性。
(3)信号与槽机制:Qt 的信号与槽机制是一种高效的事件处理机制,它允许对象之间进行松耦合的通信,提高了代码的可读性和可维护性。
(4)丰富的类库:Qt 提供了丰富的类库,包括图形界面类库、网络类库、数据库类库等,开发者可以直接使用这些类库进行开发,提高了开发效率。
4. 应用场景
(1)GUI 开发:Qt 提供了丰富的图形界面类库,开发者可以使用 Qt 开发各种类型的图形用户界面应用程序,如办公软件、游戏、媒体播放器等。
(2)网络应用程序开发:Qt 提供了强大的网络类库,开发者可以使用 Qt 开发各种类型的网络应用程序,如客户端 / 服务器应用程序、网络浏览器等。
(3)数据库应用程序开发:Qt 提供了数据库类库,开发者可以使用 Qt 开发各种类型的数据库应用程序,如数据库管理系统、数据报表生成工具等。
(4)嵌入式系统开发:Qt 可以在嵌入式系统上运行,开发者可以使用 Qt 开发各种类型的嵌入式应用程序,如智能家居设备、工业控制设备等。
5. 关键知识点
(1)GUI 开发:Qt 的图形用户界面类库提供了丰富的控件和布局管理器,开发者可以使用这些控件和布局管理器创建美观、易用的图形用户界面。
(2)信号与槽机制:Qt 的信号与槽机制是一种高效的事件处理机制,它允许对象之间进行松耦合的通信,提高了代码的可读性和可维护性。
(3)模型视图架构:Qt 的模型视图架构是一种用于处理数据和用户界面之间关系的架构,它可以提高代码的可维护性和可扩展性。
(二)Qt 库及其功能
Qt 提供了丰富的类库和工具,用于开发各种类型的应用程序。这些类库和工具包括基础类库、图形和图像处理类库等。
1. Qt 基础类库
(1)Qt 核心类库
Qt 核心类库是 Qt 框架的基础,它提供了应用程序开发的基本功能,如对象管理、事件处理、信号与槽机制等。Qt 核心类库中的主要类包括 QObject、QApplication、QWidget 等。
QObject:是 Qt 中所有对象的基类,它提供了信号与槽机制、对象树管理等功能。
QApplication:是 Qt 应用程序的入口点,它负责管理应用程序的控制流和主要设置。
QWidget:是 Qt 中所有窗口和控件的基类,它提供了窗口管理、事件处理等功能。
(2)Qt 容器类库
Qt 容器类库提供了各种数据结构的实现,如 QList、QMap、QSet 等。这些容器类库在处理数据集合时提供了高效、安全的数据存储和访问机制。
QList:类似于 C++ 的 vector,它是一个动态数组,可以存储任意类型的对象。
QMap:类似于 C++ 的 map,是一个基于键值对的关联容器,提供了快速的数据检索。
QSet:是一个无序集合,其中的元素是唯一的,适用于去重操作。
(3)Qt 工具类库
Qt 工具类库是 Qt 框架中用以提供各种辅助功能的类集合,这些功能涉及文件操作、网络编程、时间日期处理、进程与线程管理等。
QFile:提供了对文件的读写操作,支持文本和二进制模式。
QNetworkAccessManager:简化了网络请求的发送和接收过程。
QDateTime:可以用来处理日期和时间,支持时区和本地化。
2. 图形和图像处理
(1)图形视图框架
Qt 的图形视图框架提供了一套用于展示和操作大量自定义图形项和复杂场景的高级接口。它特别适用于那些需要渲染大量对象的应用程序,例如游戏、模拟器和绘图程序等。
图形项(QGraphicsItem):可以绘制在场景(QGraphicsScene)中,而视图(QGraphicsView)则负责显示场景的一部分并处理用户输入。
通过这种方式,图形视图框架允许开发者构建复杂的图形布局和场景,同时保持高效率的渲染。
(2)图像处理技术与应用实例
Qt 提供了强大的图像处理工具,可以方便地进行图像的加载、处理和渲染。
QImage 类提供了丰富的 API 来处理图像像素数据,而 QPixmap 类则专注于图像的显示,适用于绘制像素图形。
在应用实例中,开发者可以使用 QImage 来读取、保存和编辑图像文件,如 JPEG、PNG 等格式。
八、QT 项目开发实例
简述:分享了一些 Qt 项目开发实例,包括在国产操作系统中的学习路线,如 QT 开发环境安装、线段画板实战、时钟开发、大转盘游戏等。
1、QT 开发环境安装以配置
介绍 QT 在国产操作系统以及其他操作系统下的安装步骤,包括软件下载等内容。Qt 支持多种操作系统,其安装过程相对较为简单。用户可以从 Qt 官方网站下载适合自己操作系统的版本,目前 Qt 分为免费开源版和付费商业版,对于一般开发者来说,免费开源版已经足够满足需求。
以 Windows 系统为例,下载安装包(如 qt-opensource-windows-x86-5.14.2.exe)后,双击即可开始安装。在安装过程中,需要注册邮箱和密码,这将在后续的安装中使用。安装时可以将 Qt 的路径选择设置在合适的位置,如 D 盘,这样在后续的环境配置和开发过程中会更加方便。
安装完成后,用户可以直接运行 Qt Creator,这是 Qt 自带的集成开发环境,提供了强大的代码编辑和调试功能,还集成了 Qt Designer 等可视化工具,方便开发者进行界面设计和布局调整。
2、QT 线段画板实战
开发一个 QT 线段画板实例,用户可以在这个画板上画线段。其逻辑如下:将线段使用 QVector 进行保存,因为可能需要绘制多条线段。鼠标按下和释放的时候记录起始和终点位置,并且保存在数据列表中。鼠标移动过程中,动态刷新图像绘制,并且绘制临时坐标点(因鼠标没被释放,因此终点坐标随时变化)。
关键的消息接口包括 mousePressEvent(鼠标按下,当鼠标按下时发送该信号)、mouseReleaseEvent(鼠标释放,当鼠标释放时发送信号)以及 mouseMoveEvent(鼠标移动,注意需要设置捕获鼠标轨迹以便在鼠标移动时能及时响应)和 paintEvent(绘制,当执行 update 时刷新绘制)。
3、QT 入门开发一个时钟
主要介绍 Qt 的绘制功能,绘制一个时钟,同时涉及定时器的使用。可以使用 QTimer 类设置定时器,定时器中重要的几个函数包括 stop(停止定时器)和 start(启动定时器)。
时钟的开发涉及多个知识点,如本地时间获取、resource 资源读取图片、绘制图片以及按照中心旋转(通过 sin 或者 cos 角度计算)。在绘制过程中,需要确定圆心,将 widget 窗口使用坐标轴标注,以窗口的中间点(100,100)为原点,通过 painter.translate (width () / 2, height () / 2) 进行设置。
设置颜色值,如时针颜色值 QColor crHour = QColor (127,0, 127);分针颜色值 QColor crMinute = QColor (0,127, 127, 191);秒针颜色值 QColor crSecond = QColor (128,128, 0)。
绘制分割线,时针分割线一天有 12 个小时,在 360° 的圆盘中平均分割成 12 份,每次旋转角度为 30°。分针分割线 1 小时等于 60 分钟,时针的旋转角度应该是 6°,并且在绘制分针时有个特殊的位置,也就是当时针与分针的刻度值重合的位置。
绘制时针、分针、秒针图形,使用三角形表示针的形状,定义三针的初始位置,根据当前时间的不同进行旋转。计算时针的偏移角度为 30.0 * ((time.hour () + time.minute () / 60.0));分针的偏移角度为 6.0*(time.minute () + time.second () / 60.0);秒针的便宜角度为 time.second ()。
4、半小时教你做大转盘游戏(QT 篇)
大转盘用于抽奖使用。可以通过 Qt 的图形界面设计工具进行界面布局,设置大转盘的外观和样式。使用信号与槽机制实现用户交互,当用户点击开始按钮时,触发大转盘的旋转动画。可以使用定时器控制旋转的速度和持续时间,当旋转停止时,根据当前指针指向的位置确定中奖结果。
5、手把手教你制作【带吸附效果的线段绘制】(QT)
在鼠标靠近线条的时候线条处于高亮状态,鼠标可以拖拽线条。通过设置事件过滤器,监听鼠标移动事件,当鼠标靠近线条时,改变线条的颜色或样式以实现高亮效果。在鼠标按下时,记录线条的位置,当鼠标移动时,更新线条的位置,实现拖拽功能。
6、手把手教你开发 - 滚动效果号码抽奖(QT)
大屏幕滚动效果的抽奖软件,常用于公司年会、商业活动等。可以使用 Qt 的动画效果实现号码的滚动效果,通过定时器控制滚动的速度和持续时间。当用户点击停止按钮时,随机确定中奖号码,并显示在界面上。可以使用 QRandomGenerator 类生成随机数,确保中奖结果的随机性。
7、100 行代码实现贪吃蛇小游戏
贪吃蛇小游戏是 Qt 的基本入门案例,具有简单的设计思路。通过 Qt 的图形界面和定时器实现游戏的界面绘制和蛇的移动。使用 QRect 类表示蛇的身体部分,通过定时器控制蛇的移动速度。当蛇吃到食物时,身体长度增加,食物随机出现在游戏界面中。可以使用键盘事件控制蛇的移动方向。
8、C++ 实现《扫雷》游戏(入门经典)
经典的扫雷游戏开发过程分析以及详细解析。让小白都能上手,并且有源码可以查看更容易理解。使用 Qt 的图形界面设计工具创建游戏界面,包括雷区、数字提示、计时器等部分。通过鼠标事件实现方块的点击和标记功能,当点击方块时,根据周围雷的数量显示数字提示或触发雷的爆炸。可以使用二维数组表示雷区,记录每个方块的状态。
9、svg 转图片工具开发
可以将 svg 直接转为图片的 linux 工具。使用 Qt 的图形处理功能,读取 svg 文件的内容,然后将其转换为 QImage 或 QPixmap 对象,最后保存为常见的图片格式,如 JPEG、PNG 等。可以使用 QSvgRenderer 类加载 svg 文件,然后使用 QPainter 类进行绘制和保存。
10、Qt 网路与通信 (获取本机网络信息)
使用 Qt 的网络编程功能获取本机的网络信息,如 IP 地址、MAC 地址等。可以使用 QNetworkInterface 类获取网络接口列表,然后遍历每个接口获取相关信息。可以使用信号与槽机制实现网络状态的监测,当网络状态发生变化时,及时更新界面显示的网络信息。
11、Qt 网路与通信 (UDP 客户与服务)
实现基于 UDP 协议的客户端和服务器通信。使用 QUdpSocket 类创建 UDP 套接字,在客户端可以发送数据到服务器,服务器接收数据并进行处理后可以回复客户端。可以设置定时器控制数据的发送频率,确保通信的稳定性。
12、Qt 网络与通信(TCP 聊天室)
基本的聊天室开发,可以满足学生的网络课程设计与开发。使用 QTcpSocket 和 QTcpServer 类实现基于 TCP 协议的聊天室功能。服务器负责接收客户端的连接请求,并将客户端发送的消息转发给其他客户端。客户端可以发送消息给服务器,并接收服务器转发的其他客户端的消息。可以使用信号与槽机制实现消息的发送和接收,以及连接状态的监测。
13、Qt 多线程以及线程池
介绍 Qt 的多线程编程和线程池的使用。使用 QThread 类创建线程,将耗时的任务放在子线程中执行,避免阻塞主线程,提高程序的响应性。线程池可以管理多个线程,提高线程的复用率,减少线程创建和销毁的开销。可以使用信号与槽机制在不同线程之间进行通信。
Qt 散点图、折线图、柱状图、盒须图、饼状图、雷达图开发实例
数据可视化常用工具。使用 Qt 的图形绘制功能和数据模型实现各种类型的图表,如散点图、折线图、柱状图、盒须图、饼状图、雷达图等。可以使用 QChartView 类显示图表,QChart 类管理图表的数据和外观,QAbstractSeries 类表示图表的数据系列,QValueAxis 类表示坐标轴。通过设置数据系列和坐标轴的属性,可以定制图表的外观和显示效果。
14、取色器(QT)
可以提取屏幕中的颜色。包含 QT 对于快捷键的捕获响应,全屏截图等内容。使用 Qt 的图形处理功能和事件处理机制实现取色器功能。可以通过捕获鼠标事件,获取鼠标在屏幕上的位置,然后使用 QScreen 类获取该位置的像素颜色值。可以设置快捷键响应,方便用户快速进行取色操作。全屏截图功能可以使用 QScreen 类获取屏幕的图像,然后保存为图片文件。
15、MQTT 客户端入门开发
介绍 MQTT 协议和 Qt 中 MQTT 客户端的开发。MQTT 是一种轻量级的消息传输协议,适用于物联网等场景。使用 Qt 的网络编程功能和第三方 MQTT 库(如 Paho MQTT C++)实现 MQTT 客户端,可以连接到 MQTT 服务器,订阅主题,发布消息。可以使用信号与槽机制实现消息的接收和处理。
16、QT 文件上传带进度条实例(含源码)
实现文件上传功能,并显示上传进度条。使用 Qt 的网络编程功能和文件操作功能实现文件上传。可以使用 QHttpMultiPart 类将文件和其他数据封装成 HTTP 请求体,然后使用 QNetworkAccessManager 类发送请求。通过监听上传进度信号,可以实时更新进度条的显示。
17、Qt 音乐播放器开发实例(可毕设含源码)
乐音播放器可以下载网络中的接口来进行播放。使用 Qt 的多媒体功能实现音乐播放器,如 QMediaPlayer 类播放音频文件,QMediaPlaylist 类管理播放列表。可以使用网络编程功能下载音乐文件,或者从本地文件系统读取音乐文件。界面设计可以使用 Qt 的图形界面设计工具,实现播放、暂停、停止、上一曲、下一曲等功能。
九、QT 小案例集合
简述:介绍了 40 个 Qt 学习小案例,包括按钮使用、控件应用、字符串处理、信号槽使用、容器迭代等方面的内容,对 Qt 初学者友好。
(一)、按钮使用案例
在 Qt 中,按钮是常见的交互元素之一。以下是一些关于按钮使用的小案例。
-
不同类型按钮的创建
QPushButton:普通的命令按钮,可以通过设置文本或图标来展示不同的功能。例如:
QPushButton *button = new QPushButton("点击我", this);QToolButton:通常用于工具栏中,可以显示图标和文本,并且可以在点击时显示下拉菜单。例如:
QToolButton *toolButton = new QToolButton(this);
toolButton->setIcon(QIcon("icon.png"));
toolButton->setText("工具按钮");QRadioButton:单选按钮,用于在多个选项中选择一项。例如:
QRadioButton *radioButton = new QRadioButton("选项 1", this);QCheckBox:复选框按钮,用于选择或取消选择一个选项。例如:
QCheckBox *checkBox = new QCheckBox("勾选我", this); -
按钮的样式设置
可以通过 Qt 的样式表来设置按钮的外观。例如,设置按钮的背景颜色、边框、字体等。QPushButton *button = new QPushButton("点击我", this);
button->setStyleSheet("background-color: blue; color: white; border: 1px solid black;"); -
按钮的信号与槽连接
当按钮被点击时,可以触发一个信号,可以通过连接信号和槽来实现相应的功能。例如:connect(button, SIGNAL(clicked()), this, SLOT(onButtonClicked()));
在槽函数中可以实现具体的功能,比如弹出一个消息框。
void MainWindow::onButtonClicked()
{
QMessageBox::information(this, "提示", "按钮被点击了!");
}
(二)、控件应用案例
Qt 提供了丰富的控件,可以满足不同的需求。以下是一些控件应用的小案例。
-
QLineEdit:文本输入框,可以用于接收用户输入的文本。例如:
QLineEdit *lineEdit = new QLineEdit(this);
lineEdit->setText("默认文本");
可以通过信号与槽连接来获取用户输入的文本。
connect(lineEdit, SIGNAL(textChanged(QString)), this, SLOT(onLineEditTextChanged(QString)));
在槽函数中可以处理用户输入的文本。
void MainWindow::onLineEditTextChanged(const QString &text)
{
qDebug() << "用户输入的文本:" << text;
}
-
QComboBox:下拉列表框,可以用于选择一个选项。例如:
QComboBox *comboBox = new QComboBox(this);
comboBox->addItem("选项 1");
comboBox->addItem("选项 2");
comboBox->addItem("选项 3");
可以通过信号与槽连接来获取用户选择的选项。
connect(comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onComboBoxIndexChanged(int)));
在槽函数中可以处理用户选择的选项。
void MainWindow::onComboBoxIndexChanged(int index)
{
qDebug() << "用户选择的选项索引:" << index;
}
-
QListWidget:列表框,可以用于显示一个列表项。例如:
QListWidget *listWidget = new QListWidget(this);
listWidget->addItem("列表项 1");
listWidget->addItem("列表项 2");
listWidget->addItem("列表项 3"); -
可以通过信号与槽连接来获取用户选择的列表项。
connect(listWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(onListWidgetItemClicked(QListWidgetItem*)));
在槽函数中可以处理用户选择的列表项。
void MainWindow::onListWidgetItemClicked(QListWidgetItem *item)
{
qDebug() << "用户选择的列表项:" << item->text();
}
-
QTableWidget:表格控件,可以用于显示一个表格。例如:
QTableWidget *tableWidget = new QTableWidget(this);
tableWidget->setRowCount(3);
tableWidget->setColumnCount(3);
tableWidget->setItem(0, 0, new QTableWidgetItem("单元格 1"));
tableWidget->setItem(0, 1, new QTableWidgetItem("单元格 2"));
tableWidget->setItem(0, 2, new QTableWidgetItem("单元格 3"));
可以通过信号与槽连接来获取用户选择的单元格。
connect(tableWidget, SIGNAL(cellClicked(int, int)), this, SLOT(onTableWidgetCellClicked(int, int)));
在槽函数中可以处理用户选择的单元格。
void MainWindow::onTableWidgetCellClicked(int row, int column)
{
qDebug() << "用户选择的单元格:" << row << "," << column;
}
字符串处理案例
在 Qt 中,字符串处理是常见的操作之一。以下是一些字符串处理的小案例。
- QString 的基本操作
字符串拼接:可以使用 + 运算符或 append 函数来拼接字符串。例如:
QString str1 = "Hello";
QString str2 = "World";
QString str3 = str1 + " " + str2;
qDebug() << str3; // 输出:Hello World
str1.append(str2);
qDebug() << str1; // 输出:HelloWorld
字符串查找:可以使用 indexOf 函数来查找字符串中的子字符串。例如:
QString str = "Hello World";
int index = str.indexOf("World");
qDebug() << index; // 输出:6
字符串替换:可以使用 replace 函数来替换字符串中的子字符串。例如:
QString str = "Hello World";
str.replace("World", "Qt");
qDebug() << str; // 输出:Hello Qt
-
QStringList 的使用
QStringList 是一个字符串列表,可以用于存储多个字符串。例如:QStringList list;
list << "Hello" << "World" << "Qt";
qDebug() << list; // 输出:("Hello", "World", "Qt")
可以通过索引来访问字符串列表中的元素。
qDebug() << list[1]; // 输出:World
可以使用 append 函数来添加元素到字符串列表中。
list.append("New Item");
qDebug() << list; // 输出:("Hello", "World", "Qt", "New Item")
-
字符串转换
可以将 QString 转换为其他数据类型,也可以将其他数据类型转换为 QString。例如:
转换为整数:可以使用 toInt 函数将 QString 转换为整数。例如:QString str = "123";
int num = str.toInt();
qDebug() << num; // 输出:123
转换为浮点数:可以使用 toDouble 函数将 QString 转换为浮点数。例如:
QString str = "3.14";
double num = str.toDouble();
qDebug() << num; // 输出:3.14
转换为布尔值:可以使用 toBool 函数将 QString 转换为布尔值。例如:
QString str = "true";
bool value = str.toBool();
qDebug() << value; // 输出:true
转换为 QString:可以使用 QString::number 函数将其他数据类型转换为 QString。例如:
int num = 123;
QString str = QString::number(num);
qDebug() << str; // 输出:123
信号槽使用案例
信号槽是 Qt 中一种强大的机制,用于实现对象之间的通信。以下是一些信号槽使用的小案例。
- 基本信号槽连接
假设我们有一个按钮和一个标签,当按钮被点击时,标签的文本会发生变化。
QPushButton *button = new QPushButton("点击我", this);
QLabel *label = new QLabel("初始文本", this);
connect(button, SIGNAL(clicked()), label, SLOT(setText(QString)));
在这个例子中,当按钮被点击时,会发出 clicked 信号,这个信号会连接到标签的 setText 槽函数,从而改变标签的文本。
- 自定义信号槽
有时候,我们需要自定义信号和槽来实现特定的功能。例如:
class MyClass : public QObject
{
Q_OBJECT
public:
explicit MyClass(QObject *parent = nullptr);
signals:
void mySignal();
public slots:
void mySlot();
};
在这个例子中,我们定义了一个名为 MyClass 的类,它有一个自定义的信号 mySignal 和一个自定义的槽 mySlot。我们可以在类的内部或外部连接这个信号和槽。
MyClass *obj = new MyClass(this);
connect(obj, SIGNAL(mySignal()), obj, SLOT(mySlot()));
当我们发射 mySignal 信号时,mySlot 槽函数会被调用。
emit obj->mySignal();
-
信号槽的参数传递
信号和槽可以传递参数,以便在对象之间传递数据。例如:class Sender : public QObject
{
Q_OBJECT
public:
explicit Sender(QObject *parent = nullptr);
signals:
void sendSignal(int value);
};class Receiver : public QObject
{
Q_OBJECT
public:
explicit Receiver(QObject *parent = nullptr);
public slots:
void receiveSlot(int value);
};
在这个例子中,我们定义了两个类 Sender 和 Receiver,Sender 类有一个信号 sendSignal,它传递一个整数参数,Receiver 类有一个槽 receiveSlot,它接收一个整数参数。我们可以连接这两个信号和槽,并在发射信号时传递参数。
Sender *sender = new Sender(this);
Receiver *receiver = new Receiver(this);
connect(sender, SIGNAL(sendSignal(int)), receiver, SLOT(receiveSlot(int)));
sender->emit sendSignal(42);
当 sendSignal 信号被发射时,receiveSlot 槽函数会被调用,并接收传递的参数。
容器迭代案例
Qt 提供了一些容器类,如 QList、QMap、QVector 等,可以用于存储和操作数据。以下是一些容器迭代的小案例。
- QList 的迭代
QList 是一个动态数组,可以存储任意类型的对象。可以使用迭代器来遍历 QList。例如:
QList<int> list;
list << 1 << 2 << 3 << 4 << 5;
QList<int>::iterator it;
for (it = list.begin(); it!= list.end(); ++it)
{
qDebug() << *it;
}
在这个例子中,我们创建了一个 QList,并使用迭代器遍历了列表中的元素。
- QMap 的迭代
QMap 是一个键值对的关联容器,可以使用迭代器来遍历 QMap。例如:
QMap<QString, int> map;
map["one"] = 1;
map["two"] = 2;
map["three"] = 3;
QMap<QString, int>::iterator it;
for (it = map.begin(); it!= map.end(); ++it)
{
qDebug() << it.key() << ": " << it.value();
}
在这个例子中,我们创建了一个 QMap,并使用迭代器遍历了地图中的键值对。
- QVector 的迭代
QVector 是一个动态数组,可以存储任意类型的对象。可以使用迭代器来遍历 QVector。例如:
QVector<double> vector;
vector << 1.1 << 2.2 << 3.3 << 4.4 << 5.5;
QVector<double>::iterator it;
for (it = vector.begin(); it!= vector.end(); ++it)
{
qDebug() << *it;
}
在这个例子中,我们创建了一个 QVector,并使用迭代器遍历了向量中的元素。
十、Qt 官方实用例子
简述:展示了 Qt5.15.2 版本中的两个实用例子,ChartView 基本使用和模拟示波器。
(一)、Qt5.15.2 中的 ChartView 基本使用
在 Qt5.15.2 版本中,ChartView 是一个强大的图表绘制工具。通过搜索 "Line and BarChart Example" 可以找到关于 ChartView 的基本使用示例。
ChartView 可以绘制多种类型的图表,如折线图、曲线图、散点图、柱状图、堆叠柱状图、饼图等。以下以绘制正弦和余弦曲线为例展示 ChartView 的使用方法:
#include <QApplication>
#include <QMainWindow>
#include <QChartView>
#include <QSplineSeries>
#include <math.h>
#define pie 3.1415926
QT_CHARTS_USE_NAMESPACE
int main(int argc, char* argv[]) {
QApplication a(argc, argv);
QSplineSeries *series = new QSplineSeries();
series->setName("sin line");
for (double i = 0; i < 360; i++) {
QPointF point(i, sin(i / 360 * pie * 2));
series->append(point);
}
QSplineSeries *series1 = new QSplineSeries();
series1->setName("cos line");
for (double i = 0; i < 360; i++) {
QPointF point(i, cos(i / 360 * pie * 2));
series1->append(point);
}
QChart *chart = new QChart();
chart->setTitle("Simple line chart example");
chart->setAnimationOptions(QChart::SeriesAnimations);
chart->setTheme(QChart::ChartThemeBlueCerulean);
chart->addSeries(series);
chart->addSeries(series1);
chart->createDefaultAxes();
chart->axes(Qt::Horizontal).first()->setRange(0, 360);
chart->axes(Qt::Vertical).first()->setRange(-2, 2);
QChartView *chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
QMainWindow window;
window.setCentralWidget(chartView);
window.resize(400, 300);
window.show();
return a.exec();
}
(二)、Qt5.15.2 中的模拟示波器
通过搜索 "oscilloscope" 可以找到 Qt5.15.2 中的模拟示波器示例。模拟示波器在很多领域都有广泛的应用,如电子工程、信号处理等。
以下是一个关于模拟示波器的代码示例:
#include "widget.h"
#include "ui_widget.h"
#include <QDateTime>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget),
time(0),
showIsPause(false)
{
ui->setupUi(this);
yMaxVal = 1;
yMinVal = -1;
for (int i = angleSetWD; i < wdMax; i++) {
ui->waveWidget->addGraph();
}
ui->waveWidget->graph(Widget::angleSetWD)->setPen(QPen(QColor(0, 170, 0)));
ui->waveWidget->graph(Widget::angleOutputWD)->setPen(QPen(QColor(170, 170, 255)));
ui->waveWidget->graph(Widget::pitchWD)->setPen(QPen(QColor(200, 174, 180)));
ui->waveWidget->graph(Widget::speedSetWD)->setPen(QPen(QColor(170, 170, 0)));
ui->waveWidget->graph(Widget::speedOutputWD)->setPen(QPen(QColor(0, 255, 255)));
ui->waveWidget->graph(Widget::rollWD)->setPen(QPen(QColor(163, 200, 156)));
ui->waveWidget->graph(Widget::turnSetWD)->setPen(QPen(QColor(170, 255, 0)));
ui->waveWidget->graph(Widget::turnOutputWD)->setPen(QPen(QColor(255, 85, 0)));
ui->waveWidget->graph(Widget::yawWD)->setPen(QPen(QColor(200, 200, 80)));
ui->waveWidget->graph(Widget::accXWD)->setPen(QPen(QColor(0, 170, 127)));
ui->waveWidget->graph(Widget::accYWD)->setPen(QPen(QColor(255, 0, 127)));
ui->waveWidget->graph(Widget::accZWD)->setPen(QPen(QColor(