QT安裝方法
一、項目創建流程
-
創建項目
-
入口:通過Qt Creator的歡迎頁面或菜單欄(文件→新建項目)創建新項目。
-
項目類型:選擇「Qt Widgets Application」。
-
路徑要求:項目路徑需為純英文且不含特殊字符。
-
構建系統:默認選擇?CMake。
-
類配置:默認生成
MainWindow
類(包含UI文件)。
-
-
配置構建套件
-
選擇適用于當前平臺的構建套件(如MinGW/MSVC)。
-
若CMake配置失敗,需檢查CMake路徑或更新組件。
-
-
運行項目
-
點擊「運行」按鈕,生成默認窗口界面(含一個空Widget)。
-
二、工程文件解析
-
CMakeLists.txt
-
核心作用:定義項目構建規則、依賴關系及編譯選項。
-
關鍵配置:
cmake_minimum_required(VERSION 3.10) # 指定CMake最低版本 project(qt01 VERSION 0.1 LANGUAGES CXX) # 設置項目名稱及語言 set(CMAKE_CXX_STANDARD 17) # 指定C++標準為C++17 find_package(Qt6 REQUIRED COMPONENTS Widgets) # 引入Qt6 Widgets模塊 add_executable(qt01 main.cpp) # 定義可執行文件 target_link_libraries(qt01 PRIVATE Qt6::Widgets) # 鏈接Qt庫
-
注意事項:需通過
find_package
引入所需Qt模塊(如Widgets、Core等)。
-
-
mainwindow.h
-
功能:聲明主窗口類,繼承自
QMainWindow
。 -
關鍵代碼:
#include <QMainWindow> namespace Ui { class MainWindow; } // 前向聲明UI類 class MainWindow : public QMainWindow {Q_OBJECT // 必須包含Q_OBJECT宏以支持信號與槽 public:MainWindow(QWidget *parent = nullptr);~MainWindow(); private:Ui::MainWindow *ui; // UI對象指針 };
-
-
mainwindow.cpp
-
功能:實現主窗口類的構造函數和析構函數。
-
關鍵代碼:
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this); // 初始化UI(自動生成) } MainWindow::~MainWindow() { delete ui; } // 釋放UI對象
-
-
main.cpp
-
功能:應用程序入口,創建主窗口并啟動事件循環。
-
關鍵代碼:
#include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv); // 管理GUI程序生命周期MainWindow w;w.show(); // 顯示窗口return a.exec(); // 進入事件循環 }
-
注意:
a.exec()
是Qt事件循環的核心,負責處理用戶輸入和窗口事件。
-
-
ui_mainwindow.h
-
功能:由Qt Designer自動生成的UI布局代碼,描述窗口中的控件及其屬性。
-
三、Qt內存管理機制
-
父子對象關系
-
規則:父對象銷毀時自動刪除所有子對象。
-
示例:
QWidget *parent = new QWidget; QPushButton *button = new QPushButton(parent); // button的父對象為parent delete parent; // 自動刪除button
-
-
智能指針
-
QScopedPointer
:作用域內自動釋放內存。 -
QSharedPointer
:引用計數智能指針,共享所有權。
-
四、UI設計與信號槽
-
拖拽控件
-
通過Qt Designer在
.ui
文件中拖拽控件(如按鈕、標簽)并設置屬性(如文本、大小)。 -
示例:設置按鈕文本:
ui->pushButton->setText("點我");
-
-
自動連接槽函數
-
命名規則:
on_控件對象名_信號名()
。 -
示例:按鈕點擊槽函數:
void MainWindow::on_pushButton_clicked() {qDebug() << "按鈕被點擊"; }
-
五、注意事項
-
路徑規范:避免中文和特殊字符,防止構建失敗。
-
CMake配置:確保正確引入Qt模塊(如Widgets、Core)。
-
內存管理:優先使用父子對象關系或智能指針,避免內存泄漏。
-
UI更新:修改
.ui
文件后需重新構建以生成ui_*.h
文件。
信號與槽機制
一、概述
-
核心作用:Qt的信號與槽機制是用于對象間通信的松耦合方式,替代傳統回調函數。當對象狀態變化(事件)時發送信號,連接的槽函數自動響應。
-
特點:支持多對多連接(一個信號可綁定多個槽,多個信號可綁定一個槽),支持跨線程通信,參數類型需兼容。?
二、信號與槽的定義
-
信號(Signal)
-
聲明方式:在類中使用?
signals
?關鍵字聲明,無返回值(void
),無需實現。 -
示例:?
class MyClass : public QObject {Q_OBJECT signals:void mySignal(int value); // 信號聲明 };
-
-
槽(Slot)
-
聲明方式:在類中使用?
public/private/protected slots
?聲明,是普通成員函數,可帶參數和返回值。 -
示例:
class MyClass : public QObject {Q_OBJECT public slots:void mySlot(int data); // 槽聲明 };?
-
三、信號的發送與槽的調用
-
信號發送:通過?
emit
?關鍵字觸發信號。emit mySignal(100); // 發送信號
-
槽調用規則:
-
槽函數按連接順序依次執行。
-
槽可以是私有函數,但通過信號連接仍可調用。?
-
四、信號與槽的連接方式
-
手動連接
-
使用?
QObject::connect
?函數,語法:connect(sender, &SenderClass::signal, receiver, &ReceiverClass::slot);
-
示例:
connect(ui->pushButton, &QPushButton::clicked, this, &MainWindow::handleClick);
-
-
自動連接
-
通過槽函數命名規則?
on_對象名_信號名
,需在?setupUi
?中調用?QMetaObject::connectSlotsByName
。 -
示例:
void MainWindow::on_pushButton_clicked() { ... } // 自動連接?
-
五、連接類型與規則
-
連接類型(
Qt::ConnectionType
)類型 描述 AutoConnection
默認,根據線程自動選擇? Direct
(同線程)或?Queued
(跨線程)。DirectConnection
立即執行,槽在發送者線程運行。 QueuedConnection
異步執行,槽在接收者線程事件循環中調用。 BlockingQueuedConnection
同步執行,發送者線程阻塞直到槽完成(需跨線程)。 UniqueConnection
避免重復連接,與上述類型按位或使用。 -
參數規則
-
信號參數數量 ≥ 槽參數數量,且類型兼容。
-
示例:
// 合法:信號參數多于槽 connect(obj1, &ClassA::signal(int, QString), obj2, &ClassB::slot(int)); // 非法:槽參數多于信號 connect(obj1, &ClassA::signal(int), obj2, &ClassB::slot(int, QString));?
-
六、自定義信號與槽的條件
-
類必須直接或間接繼承?
QObject
。 -
類聲明中需包含?
Q_OBJECT
?宏。 -
信號用?
signals
?聲明,槽用?slots
?聲明。?
七、元對象編譯器(moc)
-
作用:處理 Qt 的擴展語法(如信號與槽),生成元對象代碼(
moc_*.cpp
)。 -
必要性:包含?
Q_OBJECT
?的類必須通過?moc
?編譯,否則信號與槽無法正常工作。?
八、關鍵示例
// 信號與槽定義
class Worker : public QObject {Q_OBJECT
signals:void progressUpdated(int percent);
public slots:void doWork() { // 工作邏輯emit progressUpdated(50); }
};// 連接
Worker worker;
QObject::connect(&worker, &Worker::progressUpdated, this, [](int percent) {qDebug() << "Progress:" << percent;
});?
簡單示例:
teacher.h:
// teacher.h
#include <QObject>
class Teacher : public QObject {Q_OBJECT
public:explicit Teacher(QObject *parent = nullptr) : QObject(parent) {}signals:void hungry(); // 正確信號聲明
};
student.h:
// student.h
#include <QObject>
#include <QDebug>
class Student : public QObject {Q_OBJECT
public:explicit Student(QObject *parent = nullptr) : QObject(parent) {}public slots:void treat(); // 槽函數聲明
};
student.cpp:
// student.cpp
#include "student.h"
void Student::treat() {qDebug() << "Student treats teacher"; // 修正輸出內容
}
window.h:
// window.h
#include <QWidget>
#include "teacher.h"
#include "student.h"class Window : public QWidget {Q_OBJECT
public:explicit Window(QWidget *parent = nullptr);public slots:void xiake(); // 觸發信號的方法private:Teacher *teacher;Student *student;
};
window.cpp:?
// window.cpp
#include "window.h"Window::Window(QWidget *parent) : QWidget(parent) {teacher = new Teacher(this);student = new Student(this);// 正確連接信號與槽(注意信號拼寫)connect(teacher, &Teacher::hungry, student, &Student::treat);
}void Window::xiake() {emit teacher->hungry(); // 觸發信號
}
九、注意事項
-
線程安全:跨線程通信優先使用?
QueuedConnection
。 -
命名規范:自動連接槽需嚴格遵循?
on_對象名_信號名
?格式。 -
內存管理:避免循環引用,確保對象生命周期可控。
Qt事件處理總結與歸納
一、事件簡介
-
概念
-
事件是用戶或系統產生的交互操作,通過事件循環處理,用于對象間信息交互。
-
Qt將系統消息轉換為
QEvent
對象,所有QObject
子類均可處理事件。
-
-
常見事件類型
-
用戶界面事件:鼠標事件(
QMouseEvent
)、鍵盤事件(QKeyEvent
)、觸摸事件(QTouchEvent
)。 -
系統事件:定時器事件(
QTimerEvent
)、窗口事件(QResizeEvent
)、繪圖事件(QPaintEvent
)。 -
自定義事件:繼承
QEvent
實現,用于特定需求。
-
二、事件處理機制
-
事件分發流程
-
事件隊列:操作系統消息被轉換為
QEvent
,由QCoreApplication::exec()
驅動的主事件循環處理。 -
事件傳遞:
-
事件先傳遞到焦點控件。
-
若未被處理,逐級傳遞給父控件。
-
-
-
事件處理函數
-
子類可重寫
event()
函數或特定事件處理函數(如mousePressEvent()
)。 -
示例:自定義按鈕重寫鼠標事件:
// 繼承QPushButton并重寫mousePressEvent void CustomPushButton::mousePressEvent(QMouseEvent *e) {qDebug() << "Custom按鈕被按下";QPushButton::mousePressEvent(e); // 調用父類實現,確保信號正常觸發 }
-
-
事件過濾器(Event Filter)
-
作用:攔截目標對象的事件,在事件到達前處理。
-
步驟:
-
安裝過濾器:
targetObj->installEventFilter(filterObj)
。 -
重寫
eventFilter()
:判斷事件類型并處理,返回true
攔截事件,false
繼續傳遞。
bool MainWindow::eventFilter(QObject *obj, QEvent *event) {if (obj == ui->pushButton && event->type() == QEvent::MouseButtonPress) {qDebug() << "攔截按鈕點擊";return true; // 阻止事件傳遞}return QMainWindow::eventFilter(obj, event); // 默認處理 }
-
-
三、事件與信號的區別
特性 | 事件(QEvent) | 信號(Signal) |
---|---|---|
觸發方式 | 由系統或用戶操作觸發 | 由對象主動發出(如按鈕點擊觸發clicked ) |
處理機制 | 通過事件隊列分發,可被過濾或攔截 | 直接調用連接的槽函數 |
靈活性 | 可自定義事件類型和分發邏輯 | 信號與槽通過connect 綁定,不可攔截 |
典型應用 | 底層交互(如鼠標移動、鍵盤輸入) | 邏輯響應(如按鈕點擊后的業務邏輯) |
四、QEventLoop 的應用
-
作用
-
在局部范圍內啟動事件循環,用于等待異步操作完成(如定時器、對話框關閉)。
-
-
使用場景
-
等待定時器:
QEventLoop loop; QTimer::singleShot(3000, &loop, &QEventLoop::quit); loop.exec(); // 阻塞3秒后繼續執行
-
模態對話框:
QDialog dialog; QEventLoop loop; connect(&dialog, &QDialog::finished, &loop, &QEventLoop::quit); dialog.show(); loop.exec(); // 等待對話框關閉
-
五、常見問題與解決
-
頭文件缺失
-
錯誤:
customepushbutton.h: No such file or directory
。 -
解決:在CMake中添加包含目錄:
include_directories(${PROJECT_SOURCE_DIR})
-
-
類型轉換錯誤
-
錯誤:
invalid conversion from 'QWidget' to 'QPushButton'
。 -
解決:確保自定義控件繼承自正確的基類(如
QPushButton
)。
-
-
信號未觸發
-
原因:重寫事件處理函數時未調用父類實現。
-
解決:在自定義的
mousePressEvent
中調用QPushButton::mousePressEvent(e)
。
-
六、總結
-
事件處理核心:理解事件分發流程、重寫事件函數、使用過濾器攔截事件。
-
事件與信號結合:事件處理底層交互,信號驅動業務邏輯,兩者互補。
-
開發注意事項:
-
繼承控件時確保調用父類事件函數以維持原有邏輯。
-
使用
QEventLoop
避免主線程阻塞,保持界面流暢。 -
合理使用事件過濾器實現復雜交互邏輯。
-
?
- 這是本人的學習筆記不是獲利的工具,小作者會一直寫下去,希望大家能多多監督我
- 文章會每攢夠兩篇進行更新發布(受平臺原因,也是希望能讓更多的人看見)
- 感謝各位的閱讀希望我的文章會對諸君有所幫助