Qt 框架概述

Qt 是一个跨平台的 C++ 应用程序开发框架,广泛用于开发图形用户界面程序。其核心特性包括跨平台能力、丰富的功能模块和强大的工具集。

核心概念与机制

元对象系统

Qt 扩展了标准 C++,通过元对象系统提供信号与槽机制、运行时类型信息和动态属性系统。任何需要使用这些特性的类都必须继承 QObject 并在类声明中包含 Q_OBJECT 宏。

信号与槽机制

信号与槽是 Qt 的核心通信机制,用于对象间的解耦通信。

信号是特殊成员函数,在特定事件发生时被发射:

cpp

class DataSender : public QObject {Q_OBJECT
signals:void dataReceived(const QByteArray &data);void imageProcessed(const QImage &image);
};

槽是普通成员函数,用于响应信号:

cpp

class DataProcessor : public QObject {Q_OBJECT
public slots:void handleData(const QByteArray &data) {// 处理数据}
};

连接信号与槽:

cpp

QObject::connect(sender, &DataSender::dataReceived, processor, &DataProcessor::handleData);

事件处理

Qt 应用程序基于事件循环机制,处理用户输入、定时器、网络事件等。可以重写事件处理函数来处理特定事件:

cpp

class CustomWidget : public QWidget {
protected:void mousePressEvent(QMouseEvent *event) override {// 处理鼠标点击事件}void keyPressEvent(QKeyEvent *event) override {// 处理键盘事件}
};

核心模块详解

GUI 模块

Qt GUI 模块提供基础 GUI 功能,包括窗口管理、事件处理和 OpenGL 集成。

Widgets 模块

提供丰富的 UI 控件集合:

  • QMainWindow:主窗口类,带菜单栏、工具栏和状态栏

  • QDialog:对话框基类

  • QLabel:文本和图像显示

  • QPushButton:按钮

  • QLineEdit:单行文本输入

  • QTextEdit:多行文本编辑

  • QComboBox:下拉列表框

  • QListWidget:列表视图

  • QTreeWidget:树形视图

  • QTableWidget:表格视图

Network 模块

提供网络编程支持:

  • QTcpSocket:TCP 客户端通信

  • QTcpServer:TCP 服务器

  • QUdpSocket:UDP 通信

  • QNetworkAccessManager:HTTP 通信

  • QNetworkRequest:网络请求构造

  • QNetworkReply:网络响应处理

数据处理与图像处理

数据序列化

Qt 提供多种数据序列化方式:

cpp

// JSON 数据处理
QJsonObject jsonObject;
jsonObject["name"] = "client";
jsonObject["data"] = "example data";QJsonDocument jsonDoc(jsonObject);
QByteArray jsonData = jsonDoc.toJson();// 从 JSON 解析
QJsonDocument receivedDoc = QJsonDocument::fromJson(receivedData);
QJsonObject obj = receivedDoc.object();
QString name = obj["name"].toString();

图像处理

Qt 提供强大的图像处理能力:

cpp

// 图像加载和显示
QPixmap pixmap("image.png");
QLabel *imageLabel = new QLabel;
imageLabel->setPixmap(pixmap);// 图像处理
QImage image("photo.jpg");
image = image.scaled(800, 600, Qt::KeepAspectRatio);
image = image.convertToFormat(QImage::Format_RGB32);// 绘制图像
QPainter painter;
painter.begin(&image);
painter.drawText(10, 10, "Processed Image");
painter.end();

网络通信实现

TCP 客户端实现

cpp

class NetworkClient : public QObject {Q_OBJECT
public:NetworkClient(QObject *parent = nullptr) : QObject(parent) {connect(&socket, &QTcpSocket::connected, this, &NetworkClient::onConnected);connect(&socket, &QTcpSocket::readyRead, this, &NetworkClient::onDataReceived);connect(&socket, &QTcpSocket::disconnected, this, &NetworkClient::onDisconnected);connect(&socket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::errorOccurred),this, &NetworkClient::onError);}void connectToServer(const QString &host, quint16 port) {socket.connectToHost(host, port);}void sendData(const QByteArray &data) {if (socket.state() == QAbstractSocket::ConnectedState) {// 添加数据长度前缀QByteArray packet;QDataStream stream(&packet, QIODevice::WriteOnly);stream << quint32(data.size());packet.append(data);socket.write(packet);}}void sendImage(const QImage &image) {QByteArray imageData;QBuffer buffer(&imageData);buffer.open(QIODevice::WriteOnly);image.save(&buffer, "PNG");sendData(imageData);}signals:void dataReceived(const QByteArray &data);void imageReceived(const QImage &image);void connected();void disconnected();void errorOccurred(const QString &error);private slots:void onConnected() {emit connected();}void onDataReceived() {static quint32 packetSize = 0;while (socket.bytesAvailable() > 0) {if (packetSize == 0) {if (socket.bytesAvailable() < sizeof(quint32))return;QDataStream stream(&socket);stream >> packetSize;}if (socket.bytesAvailable() < packetSize)return;QByteArray data = socket.read(packetSize);packetSize = 0;// 检查是否为图像数据if (data.startsWith("\x89PNG") || data.startsWith("\xFF\xD8")) {QImage image;if (image.loadFromData(data)) {emit imageReceived(image);}} else {emit dataReceived(data);}}}void onDisconnected() {emit disconnected();}void onError(QAbstractSocket::SocketError socketError) {emit errorOccurred(socket.errorString());}private:QTcpSocket socket;
};

HTTP 客户端实现

cpp

class HttpClient : public QObject {Q_OBJECT
public:HttpClient(QObject *parent = nullptr) : QObject(parent) {connect(&manager, &QNetworkAccessManager::finished,this, &HttpClient::onRequestFinished);}void get(const QUrl &url) {QNetworkRequest request(url);manager.get(request);}void post(const QUrl &url, const QByteArray &data) {QNetworkRequest request(url);request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");manager.post(request, data);}void uploadImage(const QUrl &url, const QImage &image) {QByteArray imageData;QBuffer buffer(&imageData);buffer.open(QIODevice::WriteOnly);image.save(&buffer, "PNG");QNetworkRequest request(url);request.setHeader(QNetworkRequest::ContentTypeHeader, "image/png");manager.post(request, imageData);}signals:void responseReceived(const QByteArray &data);void imageDownloaded(const QImage &image);void errorOccurred(const QString &error);private slots:void onRequestFinished(QNetworkReply *reply) {if (reply->error() == QNetworkReply::NoError) {QByteArray data = reply->readAll();QString contentType = reply->header(QNetworkRequest::ContentTypeHeader).toString();if (contentType.contains("image")) {QImage image;if (image.loadFromData(data)) {emit imageDownloaded(image);}} else {emit responseReceived(data);}} else {emit errorOccurred(reply->errorString());}reply->deleteLater();}private:QNetworkAccessManager manager;
};

多线程处理

使用 QThread

cpp

class DataProcessorThread : public QThread {Q_OBJECT
public:explicit DataProcessorThread(QObject *parent = nullptr) : QThread(parent) {}void processData(const QByteArray &data) {QMutexLocker locker(&mutex);this->data = data;condition.wakeOne();}signals:void processingFinished(const QByteArray &result);void imageProcessingFinished(const QImage &result);protected:void run() override {while (!isInterruptionRequested()) {QByteArray localData;{QMutexLocker locker(&mutex);if (data.isEmpty()) {condition.wait(&mutex);}localData = data;data.clear();}if (!localData.isEmpty()) {// 数据处理QByteArray result = processDataInternal(localData);emit processingFinished(result);}}}private:QByteArray processDataInternal(const QByteArray &data) {// 实际的数据处理逻辑return data.toUpper();}QByteArray data;QMutex mutex;QWaitCondition condition;
};

界面设计与数据绑定

使用 Model/View 架构

cpp

class DataModel : public QAbstractTableModel {Q_OBJECT
public:explicit DataModel(QObject *parent = nullptr) : QAbstractTableModel(parent) {}int rowCount(const QModelIndex &parent = QModelIndex()) const override {return dataList.size();}int columnCount(const QModelIndex &parent = QModelIndex()) const override {return 3;}QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override {if (!index.isValid() || role != Qt::DisplayRole)return QVariant();if (index.column() == 0) {return dataList[index.row()].timestamp;} else if (index.column() == 1) {return dataList[index.row()].type;} else if (index.column() == 2) {return dataList[index.row()].value;}return QVariant();}QVariant headerData(int section, Qt::Orientation orientation, int role) const override {if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {switch (section) {case 0: return "Timestamp";case 1: return "Type";case 2: return "Value";}}return QVariant();}void addData(const DataItem &item) {beginInsertRows(QModelIndex(), dataList.size(), dataList.size());dataList.append(item);endInsertRows();}void clear() {beginResetModel();dataList.clear();endResetModel();}private:struct DataItem {QDateTime timestamp;QString type;QVariant value;};QList<DataItem> dataList;
};

自定义控件

cpp

class ImageViewer : public QWidget {Q_OBJECT
public:ImageViewer(QWidget *parent = nullptr) : QWidget(parent) {setMinimumSize(400, 300);}void setImage(const QImage &image) {currentImage = image;update();}protected:void paintEvent(QPaintEvent *event) override {QPainter painter(this);if (!currentImage.isNull()) {QImage scaledImage = currentImage.scaled(size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);int x = (width() - scaledImage.width()) / 2;int y = (height() - scaledImage.height()) / 2;painter.drawImage(x, y, scaledImage);} else {painter.fillRect(rect(), Qt::lightGray);painter.drawText(rect(), Qt::AlignCenter, "No Image");}}void mousePressEvent(QMouseEvent *event) override {if (event->button() == Qt::LeftButton && !currentImage.isNull()) {emit imageClicked(event->pos());}}signals:void imageClicked(const QPoint &position);private:QImage currentImage;
};

完整的客户端示例

cpp

class ClientApplication : public QMainWindow {Q_OBJECT
public:ClientApplication(QWidget *parent = nullptr) : QMainWindow(parent) {setupUI();setupConnections();}private:void setupUI() {// 创建中央部件和布局QWidget *centralWidget = new QWidget;QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);// 创建网络状态显示statusLabel = new QLabel("Disconnected");mainLayout->addWidget(statusLabel);// 创建图像显示区域imageViewer = new ImageViewer;mainLayout->addWidget(imageViewer);// 创建控制按钮QHBoxLayout *buttonLayout = new QHBoxLayout;connectButton = new QPushButton("Connect");disconnectButton = new QPushButton("Disconnect");requestImageButton = new QPushButton("Request Image");buttonLayout->addWidget(connectButton);buttonLayout->addWidget(disconnectButton);buttonLayout->addWidget(requestImageButton);mainLayout->addLayout(buttonLayout);// 创建数据显示表格dataTable = new QTableView;dataModel = new DataModel(this);dataTable->setModel(dataModel);mainLayout->addWidget(dataTable);setCentralWidget(centralWidget);// 初始化网络客户端networkClient = new NetworkClient(this);httpClient = new HttpClient(this);}void setupConnections() {// 连接按钮信号connect(connectButton, &QPushButton::clicked, this, [this]() {networkClient->connectToServer("127.0.0.1", 8080);});connect(disconnectButton, &QPushButton::clicked, this, [this]() {networkClient->disconnectFromServer();});connect(requestImageButton, &QPushButton::clicked, this, [this]() {httpClient->get(QUrl("http://127.0.0.1:8080/image"));});// 连接网络客户端信号connect(networkClient, &NetworkClient::connected, this, [this]() {statusLabel->setText("Connected");});connect(networkClient, &NetworkClient::disconnected, this, [this]() {statusLabel->setText("Disconnected");});connect(networkClient, &NetworkClient::dataReceived, this, [this](const QByteArray &data) {// 处理接收到的数据DataItem item;item.timestamp = QDateTime::currentDateTime();item.type = "TCP Data";item.value = QString::fromUtf8(data);dataModel->addData(item);});connect(networkClient, &NetworkClient::imageReceived, this, [this](const QImage &image) {imageViewer->setImage(image);DataItem item;item.timestamp = QDateTime::currentDateTime();item.type = "Image Received";item.value = QString("Size: %1x%2").arg(image.width()).arg(image.height());dataModel->addData(item);});// 连接 HTTP 客户端信号connect(httpClient, &HttpClient::imageDownloaded, this, [this](const QImage &image) {imageViewer->setImage(image);});}// 成员变量QLabel *statusLabel;ImageViewer *imageViewer;QPushButton *connectButton;QPushButton *disconnectButton;QPushButton *requestImageButton;QTableView *dataTable;DataModel *dataModel;NetworkClient *networkClient;HttpClient *httpClient;
};

这些基础知识涵盖了 Qt 的核心概念、网络通信、图像处理和界面设计,足以开发出能够与服务器进行数据和图像交互的客户端程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/921258.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/921258.shtml
英文地址,请注明出处:http://en.pswp.cn/news/921258.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

net9 aspose.cell 自定义公式AbstractCalculationEngine,带超链接excel转html后背景色丢失

AbstractCalculationEngine 是 Aspose.Cells 中一个强大的抽象类&#xff0c;允许您自定义公式计算逻辑。当您需要覆盖默认计算行为或实现自定义函数时非常有用。直接上代码1. 创建自定义计算引擎using Aspose.Cells; using System;// 创建自定义计算引擎 public class CustomC…

如何监控员工的电脑?7款实用的员工电脑管理软件,探索高效管理捷径!

当销售团队在淘宝刷单、设计师用公司电脑挖矿、程序员频繁访问代码托管网站时&#xff0c;企业损失的不仅是带宽——低效、泄密、合规风险正成为隐形利润杀手。 传统管理依赖“人盯人”或抽查日志&#xff0c;但面对分布式办公与远程协作趋势&#xff0c;这些方法早已力不从心…

机器视觉软件--VisionPro、Visual Master,Halcon 和 OpenCV 的学习路线

Halcon 和 OpenCV区别 Halcon 和 OpenCV 都是计算机视觉领域的重要工具&#xff0c;但它们的设计理念、功能侧重和适用场景有显著不同。下面这个表格汇总了它们的核心区别&#xff0c;方便你快速了解&#xff1a; 开发模式与体验​​&#xff1a;Halcon 配备了强大的​​图形化…

算法-根据前序+中序遍历打印树的右视图

题目请根据二叉树的前序遍历&#xff0c;中序遍历恢复二叉树&#xff0c;并打印出二叉树的右视图数据范围&#xff1a; 0≤n≤100000≤n≤10000 要求&#xff1a; 空间复杂度 O(n)O(n)&#xff0c;时间复杂度 O(n)O(n)如输入[1,2,4,5,3],[4,2,5,1,3]时&#xff0c;通过前序遍历…

Kafka面试精讲 Day 7:消息序列化与压缩策略

【Kafka面试精讲 Day 7】消息序列化与压缩策略 在Kafka的高性能消息系统中&#xff0c;消息序列化与压缩是影响吞吐量、延迟和网络开销的核心环节。作为“Kafka面试精讲”系列的第7天&#xff0c;本文聚焦于这一关键主题&#xff0c;深入剖析其原理、实现方式、配置策略及常见…

Xterminal软件下载_Xterminal ssh远程链接工具下载__Xterminal安装包 网盘下载_Xterminal ssh远程链接工具安装包

Xterminal 作为一款国产 SSH 工具&#xff0c;专为开发人员量身打造。它支持 SSH 和 Telnet 协议连接远程服务器与虚拟机&#xff0c;无论是进行代码部署&#xff0c;还是服务器运维&#xff0c;都能轻松胜任。软件界面采用极简设计&#xff0c;黑色背景搭配白色文字&#xff0…

Lua > 洛谷

Lua > 洛谷P1000 超级玛丽游戏P1001 AB ProblemP1008 [NOIP 1998 普及组] 三连击P1035 [NOIP 2002 普及组] 级数求和P1046 [NOIP 2005 普及组] 陶陶摘苹果P1047 [NOIP 2005 普及组] 校门外的树P1085 [NOIP 2004 普及组] 不高兴的津津P1089 [NOIP 2004 提高组] 津津的储蓄计划…

小企业环境-火山方舟和扣子

背景说明 并不是说应该怎么办&#xff0c;而是基本配置有这些可以进行使用&#xff0c;具体不同企业使用的时候肯定要个性化配置。 使用了火山方舟和扣子 火山方舟 应用实验室列表 简单使用了提示词的功能&#xff0c;后端服务ARK_API_KEY 应用ID 来对应请求发送http请求…

QT-事件

Qt事件 除了信号和槽通信机制外&#xff0c;Qt中还提供了事件处理机制实现与用户的交互和对象间的通信。Qt捕获底层操作系统消息&#xff0c;进行封装之后转换为Qt事件&#xff0c;事件处理后才发出信号。 一、事件概述Qt中事件是程序内部或外部发生的动作。比如程序外部&#…

HI3519DRFCV500/HI3519DV500海思核心板IPC算力2.5T图像ISP超高清智能视觉应用提供SDK软件开发包

Hi3519DV500是一颗面向视觉行业推出的超高清智能 SoC。最高支持四路sensor输入&#xff0c;支持最高4K30fps的ISP图像处理能力&#xff0c;支持 2F WDR、多级降噪、六轴防抖、全景拼接、多光 谱融合等多种传统图像增强和处理算法&#xff0c;支持通过AI算法对输入图像进行实时降…

go 初始化组件最佳实践

Go 语言初始化最佳实践 在 Go 语言中, 有一个 init() 函数可以对程序进行包级别的初始化, 但 init() 函数有诸多不便, 例如: 无法返回错误, 进行耗时初始化时, 会增加程序启动时间。因此 init() 函数并不适用于所有初始化。 1.初始化方式 在程序进行初始化时&#xff0c;我们应…

域名暂停解析是怎么回事

域名注册和使用是需要付费的&#xff0c;如果没有及时续费&#xff0c;域名注册商就会暂停该域名的解析服务。相关数据显示&#xff0c;大约有 30% 的域名暂停解析情况是由于欠费引起的。比如&#xff0c;有个小公司的网站域名到期了&#xff0c;负责续费的员工忘记操作&#x…

前端开发的“三剑客”—— ​​HTML、CSS、JavaScript​​

前端开发的“三剑客”—— ​​HTML、CSS、JavaScript​​&#xff0c;是构建所有网页和Web应用的基石。它们分工明确又紧密协作&#xff0c;共同实现了网页的“内容结构”“视觉表现”和“交互行为”。以下是三者的详细解析及协作逻辑&#xff1a;​​1. HTML&#xff1a;网页…

TDengine TIMEDIFF() 函数用户使用手册

TDengine TIMEDIFF() 函数详细使用手册 目录 功能概述函数语法参数说明返回值说明版本变更说明技术特性使用场景及示例时间单位处理数据类型兼容性注意事项常见问题最佳实践 功能概述 TIMEDIFF() 函数用于计算两个时间戳的差值&#xff0c;返回 expr1 - expr2 的结果。结果…

数据结构:栈和队列(上)

汇总代码见&#xff1a;登录 - Gitee.com 上一篇文章&#xff1a;数据结构&#xff1a;双向链表-CSDN博客 与本文相关的结构体传参&#xff1a;自定义类型&#xff1a;结构体-CSDN博客 1.栈 1.1概念和结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端…

文档抽取技术:提取非结构化文档中的关键信息,提升档案管理、金融保险和法律合规领域的效率与准确性

在信息爆炸的时代&#xff0c;各种机构、企业等都面临着海量非结构化文档数据的挑战。报告、合同、票据、档案记录、法律文书等文档中蕴藏着巨大的数据&#xff0c;但传统依靠人工阅读、理解和录入的方式效率低下、成本高昂且容易出错。文档抽取技术作为人工智能和自然语言处理…

雷柏VT1 MAX评测:原生中小手形电竞鼠标 但既不仅限于中小手形 也不仅限于电竞

一、前言&#xff1a;真正针对中小手形设计的电竞鼠标 雷柏第二代VT系列电竞鼠标我们已经体验过很多款了&#xff0c;基本都是针对大中手形设计的外形模具&#xff0c;只有VT3s系列是VT3系列的缩小版&#xff0c;更适合中小手形使用&#xff0c;但也只是对中大手形模具重新优化…

新客户 | TDengine 时序数据库赋能开源鸿蒙物联展区实时监控与展示

在工业物联网快速发展的当下&#xff0c;企业普遍面临着两大挑战&#xff1a;一是设备种类繁多、接入标准不一&#xff0c;导致系统建设容易陷入“数据孤岛”&#xff1b;二是实时监控和多场景联动的需求越来越强烈&#xff0c;但传统数据库在高频写入与多维分析上难以兼顾&…

深入剖析 ConcurrentHashMap:Java 并发编程的基石

目录 【1】Java 7 中 ConcurrentHashMap 的实现原理 1.分段锁&#xff08;Segment&#xff09; 2. 数据结构 3. 操作流程 【2】Java 8 中 ConcurrentHashMap 的改进 1.红黑树的引入 2.CAS 操作 3.数据结构的变化 【3】ConcurrentHashMap 的常用方法及使用示例 1.put(…

【会员专享数据】2020-2022年我国乡镇的逐日地表气压数据(Shp/Excel格式)

之前我们分享过2020—2022年中国0.01分辨率逐日地表气压栅格数据&#xff08;可查看之前的文章获悉详情&#xff09;&#xff01;该数据是研究者张凌, 胡英屹等发布在国家冰川冻土沙漠科学数据中心平台上的高分辨地表气压数据。很多小伙伴拿到数据后反馈栅格数据不太方便使用&a…