從數據持久化到網絡通信與OpenCV:Qt應用程序開發的深度探索與實戰

文章目錄

  • 前言
  • 一、QSettings:輕量級數據持久化方案
    • 1.1 QSettings 主要特點
    • 1.2 QSettings 常用函數整理
  • 二、數據庫
    • 2.1 連接SQLite數據庫
    • 2.2 建表
    • 2.3 增刪改
  • 三、網絡編程
    • 3.1 網絡分層
    • 3.2 IP地址
    • 3.3 端口號
    • 3.4 基于TCP的Socket通信
    • 3.4 相關接口
      • 3.4.1核心類
      • 3.4.2 通信原理圖
      • 3.4.3 項目配置
      • 3.4.4 常用函數與信號
        • 3.4.4.1 QTcpServer (服務器端)
      • 3.4.5 QTcpSocket (客戶端和服務器端通信對象)
        • 3.4.5.1 QIODevice (所有 IO 設備基類)
        • 3.4.5.2 數據讀寫方式
        • 3.4.5.3 QByteArray
        • 3.4.5.4 QTextStream
    • 3.5 代碼示例
  • 四、QT中的OpenCV
    • 4.1 OpenCV簡介
    • 4.2 環境搭建
  • 4.3 人臉檢測
  • 4.4 代碼示例
  • 五、Qt程序打包
    • 5.1 設置應用程序圖標
    • 5.2 Debug版本與Release版本:構建應用程序的兩種模式
  • 5.2 打包
  • 最終章-項目演練
    • 項目要求
    • 實現功能
    • 項目演示
  • 結語


前言

在Qt基礎知識的扎實積累后,我們今天的重點將轉向Qt應用程序中至關重要的一環——數據持久化。高效且安全地存儲數據是任何復雜應用不可或缺的基礎。我們將深入探討Qt提供的數據存儲機制,從簡單的文本文件到結構化的二進制文件,再到強大的數據庫集成,旨在為您構建穩定、可擴展的Qt應用程序奠定堅實基礎。


一、QSettings:輕量級數據持久化方案

數據持久化 是指將內存中的數據模型轉換為存儲模型,以及將存儲模型轉換為內存中的數據模型的統稱。數據庫是一種常見的數據持久化方式,但對于嵌入式系統等資源受限的環境,即使是 SQLite 這樣的輕量級數據庫也可能顯得“重”。

QSettings 是 Qt 框架提供的一種比數據庫更輕量級的數據持久化方式,特別適用于存儲應用程序的配置信息、用戶偏好設置等小型數據。

1.1 QSettings 主要特點

輕量級: 無需復雜的數據庫管理系統,直接讀寫配置文件。
跨平臺: QSettings 自動處理不同操作系統下配置文件的存儲位置和格式(如 Windows 注冊表、macOS Plist 文件、Unix/Linux INI 文件等)。
簡單易用: 提供直觀的 API 進行鍵值對的讀寫。

1.2 QSettings 常用函數整理

構造函數

QSettings::QSettings(const QString & fileName, Format format, QObject * parent = 0)

參數1 fileName:存儲文件的名稱。對于INI格式,這是文件的實際名稱。對于其他格式(如Windows注冊表),QSettings 會根據應用程序和組織名稱自動確定路徑。默認為構建目錄下的一個文件。
參數2 format: 存儲格式。QSettings支持多種格式,如 QSettings::IniFormat (INI文件)、QSettings::NativeFormat (操作系統原生格式,如注冊表) 等。
參數3 parent:父對象。

設置INI文件編碼

void QSettings::setIniCodec(const char * codecName)

用途: 建議在使用INI文件格式時調用此函數,將編碼設置為 UTF-8,以避免亂碼問題。
參數 codecName: 編碼字符串,如 “UTF-8”。

數據寫入函數

beginWriteArray:以數組方式存儲(相同類型數據建議使用)

void QSettings::beginWriteArray(const QString & prefix)

用途: 當您有一組相同類型的數據需要存儲時(例如,一系列窗口位置,或一組文件路徑),beginWriteArray 提供了更結構化的方式。它會將數據存儲為數組形式。
參數 prefix: 數組的名稱。

beginGroup:以組方式存儲(不同類型數據建議使用,相同類型也可以但性能不如數組方式)

void QSettings::beginGroup(const QString & prefix)

用途: 用于組織不同類型的數據,或者將相關的鍵值對分組。這有助于保持配置文件的整潔和可讀性。
參數 prefix: 組的名稱。

setValue:在組或數組中添加鍵值對

void QSettings::setValue(const QString & key, const QVariant & value)

用途: 這是實際寫入數據的函數。它將一個鍵 (key) 與一個值 (value) 關聯起來。
參數1 key: 數據的鍵名。
參數2 value: 數據的值。QVariant 類型允許存儲多種數據類型(如 int, QString, bool 等)。
結束存儲函數

endArray:結束數組的存儲

void QSettings::endArray()

用途: 匹配 beginWriteArray,標志著當前數組寫入的結束。

endGroup:結束組的存儲

void QSettings::endGroup()

用途: 匹配 beginGroup,標志著當前組寫入的結束。
數據讀取函數

value:根據鍵獲得值

QVariant QSettings::value(const QString & key, const QVariant & defaultValue = QVariant()) const

用途: 從配置文件中讀取與指定鍵關聯的值。
參數1 key: 要讀取數據的鍵名。
參數2 defaultValue: 如果指定的鍵不存在,則返回此默認值。這可以避免讀取失敗導致程序崩潰。
返回值: 返回一個 QVariant 對象,您需要將其轉換為所需的數據類型(例如,value(“myKey”).toInt() 或 value(“anotherKey”).toString())。

代碼示例
代碼包


二、數據庫

Qt 提供了強大的機制來操作各種常見的數據庫系統。
本次課程重點: 使用 SQLite 數據庫。
原因: Qt 內置支持 SQLite,無需額外安裝或配置。
Qt 項目配置:
在使用數據庫功能之前,必須在您的 Qt 項目的 .pro 文件中添加 sql 模塊:

QT += sql

主要數據庫相關類:

QSqlDatabase: 數據庫連接類。
負責建立、管理和斷開與數據庫的連接。

QSqlError: 數據庫錯誤信息類。
用于獲取和解析數據庫操作過程中可能出現的錯誤信息。

QSqlQuery: 數據庫操作類。
用于執行 SQL 查詢語句(如 SELECT, INSERT, UPDATE, DELETE 等)。

Qt常見數據庫:

數據庫類型驅動名特點
SQLiteQSQLITE輕量級、嵌入式、文件型數據庫。非常適合桌面應用、移動應用、嵌入式系統,無需單獨的服務器進程。Qt對其支持非常好,是許多Qt應用的首選。
MySQLQMYSQL廣泛使用的開源關系型數據庫服務器。適用于中到大型Web應用、企業應用。
PostgreSQLQPSQL功能強大、遵循SQL標準、開源的關系型數據庫服務器。以其高級特性、數據完整性和可靠性而聞名。
ODBC (通用接口)QODBC開放數據庫連接 (Open Database Connectivity)。這是一個通用的API,允許應用程序通過ODBC驅動程序管理器連接到任何支持ODBC的數據庫。這意味著如果你有數據庫的ODBC驅動,Qt就可以通過QODBC連接它。通過ODBC可以連接以下數據庫:SQL Server, Oracle, Access, DB2以及其他許多兼容ODBC的數據庫。
OracleQOCI強大的企業級商業數據庫。Qt提供了直接的OCI (Oracle Call Interface) 驅動,提供了比ODBC更原生和高效的連接方式。
IBM DB2QDB2IBM的商業關系型數據庫系統。
Microsoft SQL ServerQODBC 或 QTDS (較少見或第三方實現)微軟的商業關系型數據庫服務器。通常通過QODBC連接最為常見。QTDS驅動如果存在,則可能提供更直接的連接,但不如QODBC通用。

2.1 連接SQLite數據庫

在Qt中連接SQLite數據庫主要涉及以下幾個步驟和關鍵函數:

  1. 添加數據庫驅動
    首先,你需要使用QSqlDatabase::addDatabase()靜態函數來添加一個數據庫連接。對于SQLite數據庫,你需要傳入 “QSQLITE” 作為類型字符串。這個函數會返回一個QSqlDatabase對象,這個對象代表了你的數據庫連接。

相關函數:

QSqlDatabase QSqlDatabase::addDatabase(const QString & type)

參數: type - 數據庫類型字符串,對于SQLite,通常是 “QSQLITE”。
返回值: 一個 QSqlDatabase 對象,代表了數據庫連接。

示例:

QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
  1. 設置數據庫名稱/路徑
    接下來,你需要使用QSqlDatabase::setDatabaseName()函數來指定SQLite數據庫文件的路徑和名稱。
    如果指定的數據庫文件不存在,SQLite會在程序嘗試打開連接時自動創建這個文件。
    如果文件路徑是相對路徑,它會相對于當前應用程序的執行目錄。
    成功連接后,你可以在構建目錄(通常是你的項目編譯輸出目錄)中找到生成的數據庫存儲文件。你可以使用SQLiteSpy等工具打開此文件進行查看和輔助開發。

相關函數:

void QSqlDatabase::setDatabaseName(const QString & name)

參數: name - 數據庫文件的路徑和名稱。例如,“my_database.db” 或 “C:/path/to/my_database.db”。

示例:

db.setDatabaseName("my_database.db"); // 或者 db.setDatabaseName("/path/to/my_database.db");
  1. 打開數據庫連接
    使用QSqlDatabase::open()函數嘗試打開數據庫連接。這個函數會返回一個布爾值,指示連接是否成功。

相關函數:

bool QSqlDatabase::open()

返回值: true 表示連接成功,false 表示連接失敗。

示例:

if (!db.open()) {// 處理連接失敗的情況qDebug() << "Database connection failed!";// 可以通過 db.lastError().text() 獲取詳細錯誤信息
} else {qDebug() << "Database connected successfully!";
}
  1. 檢查連接狀態和處理錯誤
    在打開連接之后,或者在進行其他數據庫操作時,最好檢查連接是否成功。

QSqlDatabase::isOpen() 可以檢查當前連接是否處于打開狀態。
QSqlDatabase::lastError() 返回一個 QSqlError 對象,其中包含了上一次數據庫操作的錯誤信息。
QSqlError::text() 可以從 QSqlError 對象中提取可讀的錯誤信息文本。

相關函數:

bool QSqlDatabase::isOpen() const

返回值: true 如果連接已打開,否則 false。

QSqlError QSqlDatabase::lastError() const

返回值: 一個 QSqlError 對象,包含上一次操作的錯誤信息。

QString QSqlError::text() const

返回值: 錯誤信息的文本描述。

示例:

if (!db.open()) {qDebug() << "Error: Failed to connect to database." << db.lastError().text();
}
// 在其他地方,你可以檢查連接狀態
if (db.isOpen()) {qDebug() << "Database is currently open.";
} else {qDebug() << "Database is currently closed.";
}
  1. 關閉數據庫連接
    當不再需要數據庫連接時,使用QSqlDatabase::close()函數關閉連接。這會釋放相關的資源。

相關函數:

void QSqlDatabase::close()

示例:

db.close();
qDebug() << "Database connection closed.";

總結連接流程

QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); // 添加SQLite驅動
db.setDatabaseName("your_database.db"); // 設置數據庫文件路徑
if (!db.open()) { ... } // 嘗試打開連接,并檢查結果
db.close(); // 完成操作后關閉連接

通過以上步驟,你就可以在Qt應用程序中成功連接和管理SQLite數據庫了!


2.2 建表

目標: 在數據庫中創建一個新的表。

所需類和函數:

QSqlQuery: 用于執行SQL語句的核心類。
QSqlError: 用于獲取SQL操作的錯誤信息。

核心函數回顧:

QSqlQuery::QSqlQuery() (構造函數)

作用: 創建一個QSqlQuery對象。默認情況下,它會關聯到當前的默認數據庫連接。如果你有多個數據庫連接,可以使用QSqlQuery(QSqlDatabase db)構造函數指定。
用法: QSqlQuery query; 或 QSqlQuery query(myDatabaseConnection);

bool QSqlQuery::exec(const QString & query) (執行SQL語句)

作用: 執行傳入的SQL語句。
參數: query - 一個QString類型的SQL語句。
返回值: true表示SQL語句執行成功,false表示執行失敗。
用法: bool success = query.exec(“CREATE TABLE MyTable (id INTEGER PRIMARY KEY, name TEXT)”);

QSqlError QSqlQuery::lastError() const (返回上一次操作的錯誤信息)

作用: 當exec()返回false時,可以使用此函數獲取詳細的錯誤信息,以便診斷問題。
返回值: 一個QSqlError對象,包含了錯誤類型、錯誤文本等信息。
用法: QSqlError error = query.lastError();

打開db文件查看:
在你的項目構建目錄(通常是build-yourprojectname-Desktop_Qt_x_x_x_MinGW_xx_bit或類似名稱)中,你會找到一個名為 mydatabase.db 的文件。
你可以使用任何支持SQLite的數據庫瀏覽器工具來打開這個 .db 文件,例如:
SQlitSpy 點擊下載
DB Browser for SQLite (推薦,免費且功能強大)
SQLiteStudio
各種集成開發環境(如VS Code with SQLite Viewer插件)
打開后,你將能夠看到新創建的 users 表及其定義的字段。


2.3 增刪改

在使用 QSqlQuery 進行數據庫的增刪改(以及復雜的查詢)操作時,推薦使用預處理語句配合參數綁定。這比直接拼接 SQL 字符串更加安全和高效。

核心函數介紹:

bool QSqlQuery::prepare(const QString & query)

功能:送入一個 SQL 預處理語句,以便于后續二次處理。這是使用預處理語句的第一步。

參數:
query (const QString &): 包含 SQL 語句的字符串。
特點:這個 SQL 語句中可以包含參數占位符。常見的占位符有:
命名占位符 (Named Placeholders):例如 :name, :id
位置占位符 (Positional Placeholders):例如 ? (對于大多數數據庫,包括 SQLite, PostgreSQL, MySQL)

示例:
INSERT INTO users (name, age) VALUES (?, ?)
UPDATE products SET price = :newPrice WHERE id = :productId
返回值:bool。如果預處理成功 (即 SQL 語法無誤,數據庫驅動能解析),返回 true;否則返回 false。

作用:在內部,數據庫驅動會解析這個 SQL 語句,并為后續的參數綁定和執行做好準備。

void QSqlQuery::addBindValue(const QVariant & val)

功能:綁定輸入參數到預處理語句中的占位符。

參數:
val (const QVariant &): 要綁定的值。QVariant 是 Qt 的通用數據類型,可以兼容各種常見的 Qt 數據類型(如 int, QString, double, QDateTime 等),提供了極大的靈活性。

作用:當你調用 prepare() 后,SQL 語句中的占位符需要被實際的值填充。addBindValue() 就是用來提供這些實際值的。

綁定順序/方式:
位置占位符 (?):按照你調用 addBindValue() 的順序,依次綁定到 SQL 語句中的 ? 占位符。例如,第一個 addBindValue() 對應第一個 ?,第二個對應第二個 ?。
命名占位符 (:name):在某些數據庫驅動中,addBindValue() 也可以用來綁定命名占位符,但更常見和推薦的方式是使用 QSqlQuery::bindValue(const QString & placeholder, const QVariant & val)。然而,如果數據庫驅動支持,多次調用 addBindValue() 也可以按照命名占位符在 SQL 語句中的出現順序進行綁定。

注意:每次執行預處理語句前,你需要為所有的占位符調用相應的 addBindValue() 或 bindValue()。

bool QSqlQuery::exec()

功能:執行已經預處理并綁定了參數的 SQL 語句。
參數:無。

返回值:bool。如果執行成功(例如 INSERT 成功,UPDATE 成功,即使沒有行被更新也算成功),返回 true;否則返回 false。

作用:將準備好的 SQL 語句及其綁定好的參數發送到數據庫執行。對于 INSERT, UPDATE, DELETE 語句,成功執行后可以通過 QSqlQuery::numRowsAffected() 獲取受影響的行數。對于 SELECT 語句,成功執行后可以通過 QSqlQuery::next() 遍歷查詢結果。


三、網絡編程

3.1 網絡分層

為什么要分層??由于結點之間聯系很復雜,在制定協議時,把復雜成份分解成??一些簡單的成份,再將它??們復合起來。最常用的復合方式是層次方式,即同層間可以通信、上一層可以調用下一層??而與再下一層不發生關系。各層互不影響,利于系統的開發和擴展。?
在這里插入圖片描述

3.2 IP地址

定義: Internet Protocol (互聯網協議) 的縮寫。是網絡中每個設備的通信地址,類似于門牌號,是網絡通信的核心條件。
在這里插入圖片描述

格式: 可以是 IPv4 或 IPv6 格式,其中 IPv4 更常用。
用途: 標識網絡中的唯一設備。
操作:
在 Windows 命令行中使用 ipconfig 命令可以查看當前計算機在局域網中的 IP 地址。
在這里插入圖片描述

可以使用 ping 命令測試網絡連通性。
在這里插入圖片描述

注意: Windows 默認開啟防火墻以保障網絡安全,進行局域網編程時可能需要關閉防火墻。

3.3 端口號

定義: 用于在一臺設備上唯一標識一個程序。
用途:
在知道 IP 地址或域名的情況下,如果想與該計算機上的特定程序交換數據,還必須知道該程序使用的端口號。
同一臺計算機中,不同的程序使用不同的端口號,以確保信息發送到各自對應的程序。
范圍:
一臺計算機上最多可以有 65536 個端口號(1-65535)。
重要提示: 1024 以下的端口號是預留給一些著名應用程序使用的,不建議占用,例如:
HTTP: 80
FTP: 21
SMTP: 25
POP3: 110

3.4 基于TCP的Socket通信

TCP (Transmission Control Protocol): 傳輸控制協議。
在這里插入圖片描述

特性: 是一種基于連接的協議。
連接建立: 在正式收發數據之前,必須先與對方建立可靠的連接。這個連接建立過程需要經過“三次對話”,被稱為三次握手。
三次握手步驟:
詢問: (客戶端發送連接請求)
確定: (服務器回應并確認收到請求)
連接: (客戶端再次確認,連接正式建立)


3.4 相關接口

您提供的文本內容是對Qt網絡編程中TCP相關類(QTcpServer和QTcpSocket)及其常用接口、通信原理和讀寫方式的詳細說明。為了更好地理解和整理,我將對內容進行結構化和補充,并對關鍵點進行提煉。

3.4.1核心類

Qt 提供了兩個主要的類用于 TCP 網絡編程:

  • QTcpServer:
    • 作用: 基于 TCP 的服務器管理類。
    • 特點: 自身不具備任何 IO (輸入/輸出) 功能,主要負責監聽客戶端連接請求。
  • QTcpSocket:
    • 作用: 基于 TCP 的通信連接類。
    • 特點: 間接繼承自 QIODevice,因此具備讀寫數據的功能。它是客戶端與服務器之間實際進行數據交換的載體。

3.4.2 通信原理圖

+----------------+                       +----------------+
|    Server      |                       |     Client     |
| (QTcpServer)   |                       | (QTcpSocket)   |
+----------------+                       +----------------+|                                        ||  1. 監聽端口 (listen)                   ||                                        ||<---------------------------------------|  2. 連接到服務器 (connectToHost)|     (客戶端發起連接請求)                 ||                                        ||  3. newConnection() 信號發出            ||                                        ||  4. nextPendingConnection()            ||     (服務器“下蛋”得到一個QTcpSocket)     ||                                        |
+-------V-------+                       +----------------+
| QTcpSocket    | <-------------------> | QTcpSocket     |
| (服務器端)     |   5. 建立連接         | (客戶端)        |
+---------------+                       +----------------+|                                         ||<--------------------------------------->|  6. 數據讀寫 (readAll, QTextStream, write)|     (通過各自的QTcpSocket進行數據通信)    |

3.4.3 項目配置

要在 Qt 項目中使用網絡功能,需要在 .pro 文件中添加網絡模塊:

QT += network

3.4.4 常用函數與信號

3.4.4.1 QTcpServer (服務器端)
  • 構造函數: QTcpServer::QTcpServer(QObject * parent = 0)
  • 監聽: bool QTcpServer::listen(const QHostAddress & address = QHostAddress::Any, quint16 port = 0)
    • 功能: 開啟服務器監聽,等待客戶端連接請求。
    • 參數:
      • address: QHostAddress 是 IP 地址的封裝類。QHostAddress::Any 表示監聽所有可用 IP 地址上的請求。
      • port: 服務器端口號。0 表示隨機分配一個可用端口。
    • 返回值: true 表示監聽成功,false 表示失敗 (常見失敗原因為端口被占用)。
  • 判斷是否監聽: bool QTcpServer::isListening() const
  • 關閉服務器: void QTcpServer::close()
  • 信號:
    • void QTcpServer::newConnection(): 當有新客戶端連接建立時發出此信號。
  • 獲取待處理連接: QTcpSocket * QTcpServer::nextPendingConnection()
    • 功能: 在 newConnection() 信號發出后調用此函數,服務器會“下蛋”生成一個 QTcpSocket 對象,用于與剛剛連接的客戶端進行通信。這個 QTcpSocket 對象是服務器與該客戶端通信的“綠蛋”。

3.4.5 QTcpSocket (客戶端和服務器端通信對象)

  • 構造函數: QTcpSocket::QTcpSocket(QObject * parent = 0)
  • 連接到主機: void QAbstractSocket::connectToHost(const QString & hostName, quint16 port, OpenMode openMode = ReadWrite)
    • 功能: 客戶端發起連接請求到指定服務器。
    • 參數:
      • hostName: 服務器的 IP 地址或域名。
      • port: 服務器的端口號。
      • openMode: IO 打開模式,默認為 ReadWrite (讀寫模式)。
  • 判斷 IO 流是否打開: bool QIODevice::isOpen() const
  • 獲取對方 IP 地址: QHostAddress QAbstractSocket::peerAddress() const
  • 獲取對方端口號: quint16 QAbstractSocket::peerPort() const
  • 獲取 IP 地址字符串: QString QHostAddress::toString() const
    • 注意: 某些系統可能會返回多余字符,需要自行裁剪。
  • 信號:
    • void QAbstractSocket::connected(): 當成功連接到服務器時發出此信號 (客戶端)。
    • void QAbstractSocket::disconnected(): 當連接斷開時發出此信號 (客戶端或服務器端)。
3.4.5.1 QIODevice (所有 IO 設備基類)
  • 信號:
    • void QIODevice::readyRead(): 當有新內容可讀時發出此信號。
  • 讀取所有內容: QByteArray QIODevice::readAll()
    • 功能: 將當前可讀的所有數據讀取到一個 QByteArray 中。
3.4.5.2 數據讀寫方式

Qt 提供了兩種主要的讀寫接口,適用于不同場景:

3.4.5.3 QByteArray
  • 特點:
    • 使用 8 位字節作為基礎存儲單位。
    • 兼容性更好: 適用于 Qt 程序與其他非 Qt 程序(如 C++ 標準庫、Java、Python 等)進行通信。
    • 推薦場景: 跨語言、跨平臺或協議定義為字節流的通信。
  • 讀寫:
    • QByteArray QIODevice::readAll(): 讀取所有可用的字節數據。
    • qint64 QIODevice::write(const QByteArray & data): 寫入字節數據。
3.4.5.4 QTextStream
  • 特點:
    • 使用 16 位 QChar 作為基礎存儲單位。
    • 使用更方便: 封裝了文本格式化和解析功能,可以直接讀寫字符串、數字等。
    • 推薦場景: 僅限于 Qt 程序之間進行文本通信,尤其是不涉及復雜二進制協議的簡單文本數據交換。
  • 構造函數: QTextStream::QTextStream(QIODevice * device)
    • 功能: 將 QTextStream 綁定到一個 QIODevice (例如 QTcpSocket) 上。
  • 讀取所有文本: QString QTextStream::readAll()
    • 功能: 從關聯的 QIODevice 中一口氣讀取所有可用的文本數據。
  • 其他讀寫操作: 支持 operator<<operator>> 進行格式化輸入輸出 (例如 QTextStream << "Hello" << endl;).

3.5 代碼示例

服務器和客戶端通訊代碼示例包


四、QT中的OpenCV

4.1 OpenCV簡介

OpenCV主要通過C++實現,Python接口是基于此開發的。
C++接口在官方文檔中更靠前。
官方文檔鏈接:官方文檔

4.2 環境搭建

  • 步驟1:下載OpenCV離線包
    網盤鏈接:opencv

  • 步驟2:解壓并拷貝
    將解壓后的文件拷貝到D盤下,注意文件夾層級,避免多一層目錄。
    在這里插入圖片描述

  • 步驟3:打開Windows環境變量配置。
    在這里插入圖片描述

  • 步驟4:配置系統環境變量。
    在這里插入圖片描述

  • 步驟5:重啟電腦。

  • 步驟6:新建Qt項目并配置.pro文件
    Qt項目路徑需為英文。

在.pro文件中添加以下OpenCV庫路徑:

INCLUDEPATH += D:/opencv/opencv3.4-install/install/include
INCLUDEPATH += D:/opencv/opencv3.4-install/install/include/opencv
INCLUDEPATH += D:/opencv/opencv3.4-install/install/include/opencv2
LIBS += D:/opencv/opencv3.4-install/install/x86/mingw/lib/libopencv_*.a
  • 步驟7:在main.cpp中編寫測試代碼驗證環境
#include "dialog.h"
#include <QDebug>
#include <opencv2/opencv.hpp> // 引入OpenCV頭文件
using namespace cv; // 使用名字空間
int main(int argc, char *argv[])
{Mat src; // 矩陣存儲圖像,相當于ndarraysrc = imread("handsome.jpg"); // 根目錄是構建目錄if(!src.data){qDebug() << "讀取失敗!";return -1;}imshow("input", src);waitKey(0);return 0;
}

問題解決:
如果出現未響應情況,可:參考文章

4.3 人臉檢測

原理:
通過定時器獲取攝像頭采集的圖像。
使用OpenCV自帶的人臉數據模型與圖像進行比對,執行人臉檢測。
在檢測到的人臉周圍畫紅框進行標注。

QImage構造函數:

QImage(
const uchar * data,         // 圖像數據
int width,                    // 寬度(列數)
int height,                   // 高度(行數)
int bytesPerLine,            // 每一行的總通道數 = 寬度 * 通道數
Format format)                // 圖像格式

QImage轉換為QPixmap:

QPixmap QPixmap::?fromImage(const QImage & image)     [static] // 參數為要轉換的QImage圖像

4.4 代碼示例

人臉識別代碼


五、Qt程序打包

5.1 設置應用程序圖標

操作步驟如下:

第一步:準備圖標文件 (.ico 格式)

  1. 選擇圖片: 找到一張你喜歡的圖片作為應用程序圖標。
  2. 轉換格式: 借助在線網站將圖片轉換為 .ico 格式。
    • 推薦分辨率: 256 x 256 像素。
    • 在線轉換工具:
      • https://cn.office-converter.com/png-to-ico
      • https://convertio.co/zh/

重磅介紹本地轉換工具:
ImageMagick
使用命令行cmd打開
運行指令:
magic xxx.png xxx.ico
該工具極其強大,還有其他很多專業作用,請參照官網ImageMagic使用指南

  1. 命名并放置: 將轉換后的 .ico 文件正確命名(例如 icon.ico)并放置到你的 Qt 項目的工作目錄中(通常是 .pro 文件所在的目錄)。

第二步:創建資源配置文件 (.rc)

  1. 在 Qt Creator 中:

    • 選中你的項目名稱(在左側的項目視圖中)。
    • 鼠標右鍵,點擊“添加新文件”。
  2. 選擇文件類型:

    • 在彈出的窗口中,選擇
      在這里插入圖片描述
  3. 命名配置文件:

    • 輸入圖標配置文件的名稱(例如 icon_config.rc)。
    • 重要: 務必加上文件的擴展名 .rc
    • 點擊“Next”。
      在這里插入圖片描述
  4. 完成創建:

    • 在項目管理界面,直接點擊“完成”。
  5. 編輯 .rc 文件:

    • 打開剛剛創建的 .rc 文件。

    • 在這里插入圖片描述

    • 輸入以下配置參數,將 icon.ico 替換為你的圖標文件名稱:

      IDI_ICON1 ICON DISCARDABLE "icon.ico"
      

第三步:配置項目文件 (.pro)

  1. 打開 .pro 文件: 在 Qt Creator 中找到并打開你的項目 .pro 文件。

在這里插入圖片描述
2. 添加配置項:.pro 文件中,增加下面的配置項,將 icon_config.rc 替換為你的 .rc 文件名稱:
cpp //后面的參數就是rc文件的名稱 RC_FILE += test.rc

第四步:編譯運行

  1. 編譯項目: 在 Qt Creator 中點擊“構建”或“運行”按鈕。
  2. 觀察效果: 觀察編譯生成的應用程序的可執行文件圖標是否已成功設置。

在這里插入圖片描述

總結流程圖:

準備 .ico 圖標文件
創建 .rc 資源配置文件
編輯 .rc 文件,指向 .ico
修改 .pro 項目文件,引入 .rc
編譯運行項目
觀察應用程序圖標是否設置成功

5.2 Debug版本與Release版本:構建應用程序的兩種模式

在軟件開發過程中,我們通常會使用兩種主要的構建版本來編譯和打包我們的應用程序:Debug版本Release版本。它們各自有不同的用途和特點。

1. Debug版本 (調試版本)

  • 用途: 主要用于開發和調試階段。
  • 特點:
    • 包含開發信息: 生成的可執行文件中會包含大量的調試信息,例如符號表、源碼行號等。
    • 性能較低: 由于包含額外信息且通常不做性能優化,程序運行速度相對較慢。
    • 體積較大: 調試信息的加入會使生成的文件體積增大。
    • 易于調試: 調試器可以利用這些信息方便地進行斷點設置、變量查看、步進執行等操作,幫助開發者定位和修復錯誤。

2. Release版本 (發布版本)

  • 用途: 最終用于發布給用戶
  • 特點:
    • 性能優化: 編譯器會對程序進行高度優化,例如代碼精簡、內聯函數、循環展開等,以提高運行速度和效率。
    • 體積小巧: 移除了調試信息和未使用的代碼,使生成的文件體積更小。
    • 不便調試: 由于經過優化和移除了調試信息,這類程序在發布后不方便被調試。如果出現問題,定位起來會更加困難。
    • 用戶體驗: 運行速度快、體積小,更適合最終用戶使用。

在這里插入圖片描述

Debug版本是開發者的工具,旨在幫助他們高效地發現和解決問題;Release版本則是面向最終用戶的產品,追求最佳的性能和用戶體驗。我們使用Release版本打包。


主題:Qt 應用程序的動態鏈接庫 (DLL) 打包

核心概念:

  • 動態鏈接庫 (DLL):Windows 系統下的動態鏈接庫文件,包含可被多個應用程序共享的代碼和資源。Qt 應用程序在運行時會調用 Qt 庫中的接口,這些接口通常封裝在 DLL 文件中。
  • 構建目錄:Qt 項目編譯后生成可執行文件的目錄,通常包含 debugrelease 子目錄。

在沒有 Qt 開發環境的計算機上雙擊運行 Qt 生成的 .exe 可執行文件時,通常會因為缺少必要的 Qt DLL 文件而報錯。


解決方案:補充 EXE 所需的 DLL 文件

以下是打包 Qt 應用程序,使其能在無 Qt 環境計算機上運行的步驟:

  1. 準備打包根目錄:
    在這里插入圖片描述
    在這里插入圖片描述

    • Release 模式下生成的 .exe 可執行文件單獨復制到一個新的文件夾中。這個文件夾將作為最終軟件打包的根目錄。
  2. 啟動帶 Qt 環境的命令行:

    • 在 Windows 搜索框中搜索并啟動一個“帶 Qt 環境的命令行”(例如 Qt Creator 自帶的“Qt 5.xx for Desktop (MinGW / MSVC)”命令行)。
      在這里插入圖片描述
  3. 切換命令行目錄:

    • 使用命令行命令 cd 切換到您在步驟 1 中創建的軟件打包根目錄。
      • 常用命令行命令提示:
        • cd <子目錄>:進入指定子目錄。
        • cd ..:返回上級目錄。
        • dir:顯示當前目錄內容。
        • <盤符>: (例如 D:):切換到指定盤符。
  4. 執行 DLL 提取命令:

    • 在命令行中,于軟件打包根目錄執行以下命令,提取所需的 DLL 文件:
      windeployqt 可執行文件名稱.exe
      
      • 注意:可執行文件名稱.exe 替換為您的實際 .exe 文件名。
  5. 驗證:

    • 命令執行完成后,回到軟件打包根目錄,再次雙擊運行您的 .exe 文件,應該可以正常運行。
  6. 重要提示:

    • 最終的“軟件根目錄”(即打包后的文件夾)在功能上相當于開發階段的“工作目錄”和“構建目錄”的結合體,包含了運行應用程序所需的所有文件。

總結流程圖:

Qt 應用開發完成
選擇 Release 模式構建
進入構建目錄的 Release 子目錄
找到生成的 .exe 文件
新建一個空文件夾作為'軟件打包根目錄'
將 .exe 文件復制到'軟件打包根目錄'
啟動'帶 Qt 環境的'命令行
使用 'cd' 命令進入'軟件打包根目錄'
執行命令: 'windeployqt 你的應用.exe'
命令執行完成,所需 DLL 文件被復制到根目錄
在'軟件打包根目錄'雙擊運行 .exe 文件
驗證應用程序是否正常啟動和運行

5.2 打包

打包軟件:Inno Setup
在這里插入圖片描述

使用方法:使用方法博文


最終章-項目演練

恭喜所有的小伙伴們!在經歷了這么多篇博文的學習之后,我們終于迎來了Qt學習之旅的又一個里程碑——筆者的qt博文系列的結尾。這并非真正的終點,更像是一個小憩,讓我們得以回顧和鞏固所學。從最初的界面搭建到復雜的信號槽機制,從數據處理到文件操作,我們一同探索了Qt的奇妙世界。它強大的功能和優雅的C++接口,為我們的開發插上了翅膀。當然,Qt的廣闊天地遠不止于此,它還有無數的寶藏等待我們去發掘。希望這次旅程能激發大家對Qt更深層次學習的興趣,未來繼續在Qt的道路上,創造出更多精彩的應用。那么最后的最后,我們一起來自己動手做一個小項目吧!

項目要求

編寫一個聊天室

實現功能

1. 實現注冊登錄
2. 實現聊天
3. 增加歷史聊天查詢功能
4. 美化界面
5. 打包成安裝包

項目演示

[演示視頻](【基于Qt的聊天室項目】 https://www.bilibili.com/video/BV1B4j3zHEoG/?share_source=copy_web&vd_source=28f8f5f13e40ab01eafa4c84779eb390)


結語

在Qt的廣闊天地中,數據持久化、網絡通信和圖像處理是構建現代、復雜應用程序不可或缺的三大支柱。本系列文章從輕量級的QSettings到強大的數據庫集成,從TCP/IP網絡基礎到QTcpServer/QTcpSocket的實戰運用,再到Qt與OpenCV的無縫結合,最終以應用程序打包和項目實戰為收尾,希望能為您打開Qt高級應用開發的大門。盡管我們探討了諸多核心概念和技術細節,Qt的潛力遠不止于此。愿您能將這些知識融會貫通,持續探索,在Qt的道路上創作出更多創新、高效且用戶友好的軟件。未來的開發之路充滿挑戰與機遇,愿我們攜手共進,在Qt的精彩世界中不斷成長!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/82891.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/82891.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/82891.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

經典SQL查詢問題的練習第一天

首先有三張表&#xff0c;學生表、課程表、成績表 student:studentId,studentName; course:courseId&#xff0c;courseName,teacher; score:score,studentId,courseId; 接著有以下幾道題目&#xff1a; ①查詢課程編號為‘0006’的總成績&#xff1a; 首先總成績&#x…

企業級網絡管理實戰:Linux、云與容器的深度融合與優化

在數字化轉型浪潮下&#xff0c;企業網絡架構日益復雜&#xff0c;Linux系統、云計算與容器技術成為構建高效、靈活網絡的核心要素。本文將從技術原理、實踐方案、優化策略三個維度&#xff0c;深度解析企業級網絡管理中的關鍵技術&#xff0c;助力企業打造穩定、安全、可擴展的…

信號與系統速成-1.緒論

b站浙大教授雖然講的比較細&#xff0c;但是太慢了&#xff0c;不適合速成 祖師爺奧本海姆的MIT課程好像和我們教材的版本不太匹配&#xff0c;但是講的很不錯 慕課上也有很多資源&#xff0c;比如信號與系統 - 網易云課堂 同站博主籬笆外的xixi的文章也挺不錯 最終我還是選…

緩存架構方案:Caffeine + Redis 雙層緩存架構深度解析

在高并發、低延遲的現代互聯網系統中&#xff0c;緩存是提升系統性能和穩定性的重要手段。隨著業務復雜度的增長&#xff0c;單一緩存方案&#xff08;如僅使用Redis或僅使用本地緩存&#xff09;已難以滿足高性能與一致性需求。 本文將圍繞 Caffeine Redis 的雙層緩存架構展…

【Elasticsearch】track_total_hits

在 Elasticsearch 中&#xff0c;track_total_hits 是一個查詢參數&#xff0c;用于控制是否精確計算搜索結果的總命中數&#xff08;total hits&#xff09;。默認情況下&#xff0c;Elasticsearch 在某些情況下可能會對總命中數進行近似計算&#xff0c;以提高性能。track_to…

智能手機上用Termux安裝php+Nginx

Termux的官方網站&#xff1a;Termux | The main termux site and help pages. 以下是在 Termux 上安裝和配置 PHP Nginx 的完整流程總結&#xff0c;包含關鍵步驟和命令&#xff1a; 一、安裝依賴 pkg update && pkg upgrade # 更新包列表和系統pkg install nginx p…

電腦開機后出現bootmgr is conmpressed原因及解決方法

最近有網友問我為什么我電腦開機后出現BOOTMGR is compressed&#xff0c;這個提示意思是:意思是啟動管理器被壓縮了&#xff0c;即使重啟也無法正常進入系統。原因有很多&#xff0c;大部分是引導出現問題&#xff0c;或選錯了啟動硬盤所導致的&#xff0c;下面我們來詳細分析…

服務發現Nacos

目錄 Nacos server 安裝 注冊服務到Nacos server 接口訪問Nacos server中的已注冊服務 Nacos控制臺介紹 Nacos:一個更易于構建云原生應用的動態服務發現、配置管理和服務管理平臺。 在分布式服務應用中&#xff0c;各類服務需要統一的注冊、統一的管理&#xff0c;這個組件工具…

并查集 c++函數的值傳遞和引用傳遞 晴神問

目錄 學校的班級個數 手推7個班級&#xff0c;答案17&#xff1f;懷疑人生 破案了&#xff0c;應該是6個班。 破案了&#xff0c;原來寫的是 unionxy(a, b, father); c if兩個數同時為正或為負 簡潔寫法 可以用位運算&#xff1f; c可以這樣賦值嗎&#xff1f;ab2 典型…

Qt Creator快捷鍵合集

前言 QtCreator是一款跨平臺的IDE,專為Qt開發設計,支持C/C++/JS/Python編程,支持設備遠程調試,支持代碼高亮,集成幫助文檔,原生支持cmake和git,確實是一款樸實而又強大的集成開發環境,讓人有種愛不釋手的感覺 編輯 功能快捷鍵復制Ctrl + C粘貼Ctrl + V剪切Ctrl + X代…

docker網絡相關內容詳解

一、docker與k8s 一、Docker 核心解析 1. Docker 定義與架構 本質&#xff1a; 容器化平臺&#xff08;構建容器化應用&#xff09;、進程管理軟件&#xff08;守護進程管理容器生命周期&#xff09;。客戶端&#xff08;docker cli&#xff09;與服務端&#xff08;docker ser…

首發!PPIO派歐云上線DeepSeek-R1-0528-Qwen3-8B蒸餾模型

首發&#xff01;PPIO派歐云上線DeepSeek-R1-0528-Qwen3-8B蒸餾模型 DeepSeek R1 系列的模型更新還在繼續。 繼昨天 PPIO派歐云首發上線 DeepSeek-R1-0528 模型后&#xff0c;今天 PPIO 再次首發 DeepSeek 最新開源的蒸餾模型 DeepSeek-R1-0528-Qwen3-8B。 DeepSeek-R1-0528-Q…

如何用命令行將 PDF 表格轉換為 HTML 表格

本文將介紹如何使用命令行將可填寫的 PDF 表單轉換為 HTML 表單。只需幾行代碼即可完成轉換。將可填寫的 PDF 表單轉換為 HTML 表單后&#xff0c;你可以在網頁上顯示這些表單。本指南使用 FormVu 來演示轉換過程。 使用命令行將可填寫 PDF 表單轉換為 HTML 表單 你可以通過命…

杰發科技AC7840——CSE硬件加密模塊使用(2)

注意&#xff1a; 不要隨便修改主秘鑰&#xff0c;本次跑代碼過程中&#xff0c;對主秘鑰進行修改&#xff0c;導致無法對cse模塊恢復出廠設置 更新秘鑰例程 第2個例程主要是把cse的key加載到cse安全區域中 這里剛看到加載秘鑰并不是直接把明文加載到cse模塊 測試第3個例程 復…

淺解Vue 數據可視化開發建議與速度優化

數據可視化在現代前端應用中至關重要&#xff0c;但處理大規模數據時容易遇到性能瓶頸。以下是針對 Vue 項目的個人看法的優化方案&#xff1a; 文章目錄 一、框架選型建議二、大數據渲染優化三、渲染性能提升四、內存管理五、監控與調試六、進階優化方案七、Vue特定優化八、構…

lua腳本學習筆記1:Vscode添加lua環境_lua基本語法

下載Lua環境&#xff0c;lua語言基本語法。 目錄 lua介紹&#xff1a; VsCode添加Lua編程環境 下載Lua 配置環境變量 查詢lua環境 打開 VSCode&#xff0c;安裝 Lua 語言插件和調試器 VScode增添lua編譯器路徑 測試lua程序&#xff1a; 代碼&#xff1a; 結果&#xff1a; 參考…

Nordic nRF52832使用寄存器實現SPI功能

目錄 概述 1 SPI相關的寄存器 1.1 SPI的框架結構 1.2 功能描述 1.3 SPI Master模式引腳配置 1.4 SPI Master模式下的時序 2 SPI相關的寄存器 2.1 Instances 2.2 詳細寄存器定義 2.3 SPI master interface特性 3 Zephyr 平臺下SPI功能時序&#xff08;寄存器&#xf…

【Python辦公】將Excel表格轉json(字典)數據-可自定義key和value

目錄 專欄導讀背景介紹庫的安裝數據源準備代碼1:key1列,value所有列代碼1:key多列,value所有列代碼3:key自選,value自選總結專欄導讀 ?? 歡迎來到Python辦公自動化專欄—Python處理辦公問題,解放您的雙手 ?????? 博客主頁:請點擊——> 一晌小貪歡的博客主頁求關…

DexWild:野外機器人策略的靈巧人機交互

25年5月來自 CMU 的論文“DexWild: Dexterous Human Interactions for In-the-Wild Robot Policies”。 大規模、多樣化的機器人數據集已成為將靈巧操作策略泛化到新環境的一條有效途徑&#xff0c;但獲取此類數據集面臨諸多挑戰。雖然遙操作可以提供高保真度的數據集&#xf…

[藍帽杯 2022 初賽]網站取證_2

一、找到與數據庫有關系的PHP文件 打開內容如下&#xff0c;發現數據庫密碼是函數my_encrypt()返回的結果。 二、在文件夾encrypt中找到encrypt.php,內容如下&#xff0c;其中mcrypt已不再使用&#xff0c;所以使用php>7版本可能沒有執行結果&#xff0c;需要換成較低版本…