C++ Qt 開發核心知識

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…