終于迎來了界面開發的實戰環節!今天我們將通過純代碼的方式,親手打造一個界面。如果你對 Qt 感興趣,歡迎訂閱我的 Qt 基礎入門專欄 (完全免費哦)。雖然前面幾篇文章主要是基礎知識講解,可能會顯得稍微平淡,但它們是邁向實戰的重要基石。而今天,我們將迎來一次小型的代碼實戰——用代碼實現一個如下圖所示的完整界面!
這不僅是一次實踐的機會,更是一個讓你快速掌握 Qt 界面開發技巧的絕佳起點。讓我們一起動手,感受代碼的魅力吧!
一、思路
1、分析一下界面構成
這個界面由四種主要組件構成:復選框(用于選擇字體樣式)、單選框(用于設置字體顏色)、文本編輯框以及三個操作按鈕。為了使布局更加清晰和有序,我們可以采用三個水平布局來分別管理這些組件:
- 第一個水平布局負責排列復選框(字體樣式)。
- 第二個水平布局用于組織單選框(字體顏色)。
- 第三個水平布局則用來放置三個操作按鈕。注意一下,關閉按鈕在許多軟件中都是將其放在最右邊,所以,在添加關閉按鈕前,需要添加一個可拉伸的組件,代碼中會有,請注意一下。
接著,我們將這三組水平布局與單獨的文本編輯框依次添加到一個垂直布局中。通過這種方式,整個界面結構層次分明、整潔美觀,所有組件都能在一個統一的垂直布局中井然有序地呈現出來。
2、步驟分析
-
界面設計 :
- 使用復選框控制字體樣式(下劃線、斜體、粗體)。
- 使用單選按鈕控制文字顏色(黑色、紅色、綠色)。
- 使用文本編輯框顯示效果。
- 使用按鈕(確認、取消、關閉)提供基本操作。
-
信號與槽機制 :
- 通過信號與槽機制,將用戶操作(如點擊復選框、單選按鈕)與具體的槽函數關聯起來,動態更新文本編輯框的樣式。
-
布局管理 :
- 使用水平布局和垂直布局合理組織控件,確保界面整潔美觀。
-
內存管理 :
- 所有控件都設置了父對象,Qt 的父子機制會自動管理內存,避免手動釋放資源。
二、創建一個QDialog項目
這次選用的基類跟前面幾期的基類不一樣,這次用的是QDialog(如果不會創建,請看我第一期),如下圖所示:
三、初始化組件
1、用指針初始化變量的原因:
- 動態內存分配 :確保控件的生命周期足夠長。
- 父子機制 :支持 Qt 的自動內存管理。
- 靈活性 :允許動態創建、共享和傳遞對象。
- 節省內存 :避免不必要的對象復制。
- 設計哲學 :符合 Qt 的設計理念,特別是信號與槽機制。
2、dialog.h的代碼?
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QCheckBox>
#include <QRadioButton>
#include <QPlainTextEdit>
#include <QPushButton>
#include <QHBoxLayout> //水平布局
#include <QVBoxLayout> //垂直布局class Dialog : public QDialog
{Q_OBJECTpublic:Dialog(QWidget *parent = nullptr);~Dialog();private:void initUI(); //初始化組件的函數private://下劃線、斜體、粗體的組件QCheckBox* chkBoxUnderLine;QCheckBox* chkBoxItalic;QCheckBox* chkBoxBold;//黑色、紅色、綠色的組件QRadioButton* rBtnBlack;QRadioButton* rBtnRed;QRadioButton* rBtnGreen;//文本編輯器的組件QPlainTextEdit* txtEdit;//確定、取消、退出的組件QPushButton* btnOk;QPushButton* btnCancel;QPushButton* btnClose;//水平布局編輯器QHBoxLayout* hLayout1;QHBoxLayout* hLayout2;QHBoxLayout* hLayout3;//垂直布局編輯器QVBoxLayout* vLayout;
};
#endif // DIALOG_H
3、void initUI()的代碼
void Dialog::initUI()
{// 創建字體相關的復選框chkBoxUnderLine = new QCheckBox("下劃線"); // 下劃線復選框chkBoxItalic = new QCheckBox("斜體"); // 斜體復選框chkBoxBold = new QCheckBox("粗體"); // 粗體復選框// 創建水平布局1,并將字體相關的復選框添加到該布局中hLayout1 = new QHBoxLayout; // 創建水平布局1hLayout1->addWidget(chkBoxUnderLine); // 將下劃線復選框添加到水平布局1hLayout1->addWidget(chkBoxItalic); // 將斜體復選框添加到水平布局1hLayout1->addWidget(chkBoxBold); // 將粗體復選框添加到水平布局1// 創建顏色相關的單選按鈕rBtnBlack = new QRadioButton("黑色"); // 黑色單選按鈕rBtnBlack->setChecked(true); //默認黑色單選已選上rBtnRed = new QRadioButton("紅色"); // 紅色單選按鈕rBtnGreen = new QRadioButton("綠色"); // 綠色單選按鈕// 創建水平布局2,并將顏色相關的單選按鈕添加到該布局中hLayout2 = new QHBoxLayout; // 創建水平布局2hLayout2->addWidget(rBtnBlack); // 將黑色單選按鈕添加到水平布局2hLayout2->addWidget(rBtnRed); // 將紅色單選按鈕添加到水平布局2hLayout2->addWidget(rBtnGreen); // 將綠色單選按鈕添加到水平布局2// 創建一個多行文本編輯框,用于顯示或輸入文本txtEdit = new QPlainTextEdit; // 創建一個純文本編輯框//將文本編輯框的字體大小調大auto font = txtEdit->font();font.setPointSize(20);txtEdit->setFont(font);// 創建操作按鈕btnOk = new QPushButton("確認"); // 確認按鈕btnCancel = new QPushButton("取消"); // 取消按鈕btnClose = new QPushButton("關閉"); // 關閉按鈕hLayout3 = new QHBoxLayout; // 創建水平布局3hLayout3->addWidget(btnOk); // 將確認按鈕添加到水平布局3hLayout3->addWidget(btnCancel); // 將取消按鈕添加到水平布局3hLayout3->addStretch(); // 添加一個可拉伸的空間,使按鈕靠左對齊hLayout3->addWidget(btnClose); // 將關閉按鈕添加到水平布局3vLayout = new QVBoxLayout; // 創建垂直布局vLayout->addLayout(hLayout1); // 將水平布局1(字體復選框)添加到垂直布局vLayout->addLayout(hLayout2); // 將水平布局2(顏色單選按鈕)添加到垂直布局vLayout->addWidget(txtEdit); // 將文本編輯框添加到垂直布局vLayout->addLayout(hLayout3); // 將水平布局3(操作按鈕)添加到垂直布局setLayout(vLayout); // 將垂直布局設置為當前窗口的布局
}
四、初始化信號和槽
在QT中,想要讓按鈕和選項框生效,那么就必須引入信號和槽,因為我們用了QT自帶的組件,所以我們可以用QT中自帶的信號,至于槽函數需要我們自己去編寫
1、dialog.h的代碼?
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QCheckBox>
#include <QRadioButton>
#include <QPlainTextEdit>
#include <QPushButton>
#include <QHBoxLayout> //水平布局
#include <QVBoxLayout> //垂直布局
#include <QMessageBox>class Dialog : public QDialog
{Q_OBJECTpublic:Dialog(QWidget *parent = nullptr);~Dialog();private:void initUI();void initSignalSlots(); //初始化信號和槽private slots://字體復選框槽函數void onChkBoxUnderLine(bool checked);void onChkBoxItalic(bool checked);void onChkBoxBold(bool checked);//顏色單選框槽函數void setTextFontColor();//確認的功能按鈕void pushButtonOk();//取消的功能按鈕void pushButtonCancel();private://下劃線、斜體、粗體的組件QCheckBox* chkBoxUnderLine;QCheckBox* chkBoxItalic;QCheckBox* chkBoxBold;//黑色、紅色、綠色的組件QRadioButton* rBtnBlack;QRadioButton* rBtnRed;QRadioButton* rBtnGreen;//文本編輯器的組件QPlainTextEdit* txtEdit;//確定、取消、退出的組件QPushButton* btnOk;QPushButton* btnCancel;QPushButton* btnClose;//水平布局編輯器QHBoxLayout* hLayout1;QHBoxLayout* hLayout2;QHBoxLayout* hLayout3;//垂直布局編輯器QVBoxLayout* vLayout;
};
#endif // DIALOG_H
更新的部分?
?2、void initSignalSlots()的代碼
void Dialog::initSignalSlots()
{//復選框connect(chkBoxUnderLine, SIGNAL(clicked(bool)),this, SLOT(onChkBoxUnderLine(bool)));connect(chkBoxItalic, SIGNAL(clicked(bool)),this, SLOT(onChkBoxItalic(bool)));connect(chkBoxBold, SIGNAL(clicked(bool)),this, SLOT(onChkBoxBold(bool)));//單選框connect(rBtnBlack, SIGNAL(clicked()), this, SLOT(setTextFontColor()));connect(rBtnRed, SIGNAL(clicked()), this, SLOT(setTextFontColor()));connect(rBtnGreen, SIGNAL(clicked()), this, SLOT(setTextFontColor()));//功能按鈕connect(btnOk, SIGNAL(clicked()), this, SLOT(pushButtonOk()));connect(btnCancel, SIGNAL(clicked()), this, SLOT(pushButtonCancel()));connect(btnClose, SIGNAL(clicked()), this, SLOT(close()));
}
3、實現復選框的三個槽函數
// 當下劃線復選框被點擊時,該槽函數會被調用。
// 參數 clicked 表示復選框的當前狀態(true 表示選中,false 表示未選中)。
void Dialog::onChkBoxUnderLine(bool clicked)
{// 獲取文本編輯框當前的字體auto font = txtEdit->font();// 根據復選框的狀態設置字體的下劃線屬性font.setUnderline(clicked);// 將修改后的字體重新設置回文本編輯框txtEdit->setFont(font);
}// 當斜體復選框被點擊時,該槽函數會被調用。
void Dialog::onChkBoxItalic(bool clicked)
{// 獲取文本編輯框當前的字體auto font = txtEdit->font();// 根據復選框的狀態設置字體的斜體屬性font.setItalic(clicked);// 將修改后的字體重新設置回文本編輯框txtEdit->setFont(font);
}// 當粗體復選框被點擊時,該槽函數會被調用。
void Dialog::onChkBoxBold(bool clicked)
{// 獲取文本編輯框當前的字體auto font = txtEdit->font();// 根據復選框的狀態設置字體的粗體屬性font.setBold(clicked);// 將修改后的字體重新設置回文本編輯框txtEdit->setFont(font);
}
4、實現單選框的槽函數
// 設置文本編輯框的文字顏色
void Dialog::setTextFontColor()
{// 獲取文本編輯框的當前調色板auto palette = txtEdit->palette();// 檢查黑色單選按鈕是否被選中if (rBtnBlack->isChecked()) {// 如果黑色單選按鈕被選中,將調色板中的文字顏色設置為黑色palette.setColor(QPalette::Text, Qt::black);} // 檢查紅色單選按鈕是否被選中else if (rBtnRed->isChecked()) {// 如果紅色單選按鈕被選中,將調色板中的文字顏色設置為紅色palette.setColor(QPalette::Text, Qt::red);} // 檢查綠色單選按鈕是否被選中else if (rBtnGreen->isChecked()) {// 如果綠色單選按鈕被選中,將調色板中的文字顏色設置為綠色palette.setColor(QPalette::Text, Qt::green);}// 將修改后的調色板重新應用到文本編輯框txtEdit->setPalette(palette);
}
5、設計功能按鈕的槽函數
可以自己設計要進行的內容,我的確認按鈕是輸出文本中每一行的頭一個元素,取消按鈕就是輸出一個已取消,關閉按鈕用了QT自帶的 close() 函數
void Dialog::pushButtonOk()
{auto text = txtEdit->toPlainText(); //將文本轉換為QStringauto strList = text.split("\n");QString ret;for(auto& str: strList) {ret += str[0];}QMessageBox::information(this, "提示", ret);
}void Dialog::pushButtonCancel()
{QMessageBox::information(this, "提示", "已取消");
}
五、運行代碼
1、項目的所有代碼
1. dialog.h:?
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QCheckBox>
#include <QRadioButton>
#include <QPlainTextEdit>
#include <QPushButton>
#include <QHBoxLayout> //水平布局
#include <QVBoxLayout> //垂直布局
#include <QMessageBox>class Dialog : public QDialog
{Q_OBJECTpublic:Dialog(QWidget *parent = nullptr);~Dialog();private:void initUI();void initSignalSlots();private slots://字體復選框槽函數void onChkBoxUnderLine(bool checked);void onChkBoxItalic(bool checked);void onChkBoxBold(bool checked);//顏色單選框槽函數void setTextFontColor();//確認的功能按鈕void pushButtonOk();//取消的功能按鈕void pushButtonCancel();private://下劃線、斜體、粗體的組件QCheckBox* chkBoxUnderLine;QCheckBox* chkBoxItalic;QCheckBox* chkBoxBold;//黑色、紅色、綠色的組件QRadioButton* rBtnBlack;QRadioButton* rBtnRed;QRadioButton* rBtnGreen;//文本編輯器的組件QPlainTextEdit* txtEdit;//確定、取消、退出的組件QPushButton* btnOk;QPushButton* btnCancel;QPushButton* btnClose;//水平布局編輯器QHBoxLayout* hLayout1;QHBoxLayout* hLayout2;QHBoxLayout* hLayout3;//垂直布局編輯器QVBoxLayout* vLayout;
};
#endif // DIALOG_H
2. dialog.cpp:
#include "dialog.h"Dialog::Dialog(QWidget *parent): QDialog(parent)
{resize(800, 400);initUI();initSignalSlots();}Dialog::~Dialog()
{}void Dialog::initUI()
{// 創建字體相關的復選框chkBoxUnderLine = new QCheckBox("下劃線"); // 下劃線復選框chkBoxItalic = new QCheckBox("斜體"); // 斜體復選框chkBoxBold = new QCheckBox("粗體"); // 粗體復選框// 創建水平布局1,并將字體相關的復選框添加到該布局中hLayout1 = new QHBoxLayout; // 創建水平布局1hLayout1->addWidget(chkBoxUnderLine); // 將下劃線復選框添加到水平布局1hLayout1->addWidget(chkBoxItalic); // 將斜體復選框添加到水平布局1hLayout1->addWidget(chkBoxBold); // 將粗體復選框添加到水平布局1// 創建顏色相關的單選按鈕rBtnBlack = new QRadioButton("黑色"); // 黑色單選按鈕rBtnBlack->setChecked(true); //默認黑色單選已選上rBtnRed = new QRadioButton("紅色"); // 紅色單選按鈕rBtnGreen = new QRadioButton("綠色"); // 綠色單選按鈕// 創建水平布局2,并將顏色相關的單選按鈕添加到該布局中hLayout2 = new QHBoxLayout; // 創建水平布局2hLayout2->addWidget(rBtnBlack); // 將黑色單選按鈕添加到水平布局2hLayout2->addWidget(rBtnRed); // 將紅色單選按鈕添加到水平布局2hLayout2->addWidget(rBtnGreen); // 將綠色單選按鈕添加到水平布局2// 創建一個多行文本編輯框,用于顯示或輸入文本txtEdit = new QPlainTextEdit; // 創建一個純文本編輯框//將文本編輯框的字體大小調大auto font = txtEdit->font();font.setPointSize(20);txtEdit->setFont(font);// 創建操作按鈕btnOk = new QPushButton("確認"); // 確認按鈕btnCancel = new QPushButton("取消"); // 取消按鈕btnClose = new QPushButton("關閉"); // 關閉按鈕hLayout3 = new QHBoxLayout; // 創建水平布局3hLayout3->addWidget(btnOk); // 將確認按鈕添加到水平布局3hLayout3->addWidget(btnCancel); // 將取消按鈕添加到水平布局3hLayout3->addStretch(); // 添加一個可拉伸的空間,使按鈕靠左對齊hLayout3->addWidget(btnClose); // 將關閉按鈕添加到水平布局3vLayout = new QVBoxLayout; // 創建垂直布局vLayout->addLayout(hLayout1); // 將水平布局1(字體復選框)添加到垂直布局vLayout->addLayout(hLayout2); // 將水平布局2(顏色單選按鈕)添加到垂直布局vLayout->addWidget(txtEdit); // 將文本編輯框添加到垂直布局vLayout->addLayout(hLayout3); // 將水平布局3(操作按鈕)添加到垂直布局setLayout(vLayout); // 將垂直布局設置為當前窗口的布局
}void Dialog::initSignalSlots()
{//復選框connect(chkBoxUnderLine, SIGNAL(clicked(bool)),this, SLOT(onChkBoxUnderLine(bool)));connect(chkBoxItalic, SIGNAL(clicked(bool)),this, SLOT(onChkBoxItalic(bool)));connect(chkBoxBold, SIGNAL(clicked(bool)),this, SLOT(onChkBoxBold(bool)));//單選框connect(rBtnBlack, SIGNAL(clicked()), this, SLOT(setTextFontColor()));connect(rBtnRed, SIGNAL(clicked()), this, SLOT(setTextFontColor()));connect(rBtnGreen, SIGNAL(clicked()), this, SLOT(setTextFontColor()));//功能按鈕connect(btnOk, SIGNAL(clicked()), this, SLOT(pushButtonOk()));connect(btnCancel, SIGNAL(clicked()), this, SLOT(pushButtonCancel()));connect(btnClose, SIGNAL(clicked()), this, SLOT(close()));
}// 當下劃線復選框被點擊時,該槽函數會被調用。
// 參數 clicked 表示復選框的當前狀態(true 表示選中,false 表示未選中)。
void Dialog::onChkBoxUnderLine(bool clicked)
{// 獲取文本編輯框當前的字體auto font = txtEdit->font();// 根據復選框的狀態設置字體的下劃線屬性font.setUnderline(clicked);// 將修改后的字體重新設置回文本編輯框txtEdit->setFont(font);
}// 當斜體復選框被點擊時,該槽函數會被調用。
void Dialog::onChkBoxItalic(bool clicked)
{// 獲取文本編輯框當前的字體auto font = txtEdit->font();// 根據復選框的狀態設置字體的斜體屬性font.setItalic(clicked);// 將修改后的字體重新設置回文本編輯框txtEdit->setFont(font);
}// 當粗體復選框被點擊時,該槽函數會被調用。
void Dialog::onChkBoxBold(bool clicked)
{// 獲取文本編輯框當前的字體auto font = txtEdit->font();// 根據復選框的狀態設置字體的粗體屬性font.setBold(clicked);// 將修改后的字體重新設置回文本編輯框txtEdit->setFont(font);
}// 設置文本編輯框的文字顏色
void Dialog::setTextFontColor()
{// 獲取文本編輯框的當前調色板auto palette = txtEdit->palette();// 檢查黑色單選按鈕是否被選中if (rBtnBlack->isChecked()) {// 如果黑色單選按鈕被選中,將調色板中的文字顏色設置為黑色palette.setColor(QPalette::Text, Qt::black);} // 檢查紅色單選按鈕是否被選中else if (rBtnRed->isChecked()) {// 如果紅色單選按鈕被選中,將調色板中的文字顏色設置為紅色palette.setColor(QPalette::Text, Qt::red);} // 檢查綠色單選按鈕是否被選中else if (rBtnGreen->isChecked()) {// 如果綠色單選按鈕被選中,將調色板中的文字顏色設置為綠色palette.setColor(QPalette::Text, Qt::green);}// 將修改后的調色板重新應用到文本編輯框txtEdit->setPalette(palette);
}void Dialog::pushButtonOk()
{auto text = txtEdit->toPlainText(); //將文本轉換為QStringauto strList = text.split("\n");QString ret;for(auto& str: strList) {ret += str[0];}QMessageBox::information(this, "提示", ret);
}void Dialog::pushButtonCancel()
{QMessageBox::information(this, "提示", "已取消");
}
3. main.cpp:
#include "dialog.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Dialog w;w.show();return a.exec();
}
2、運行結果
點擊確認?
點擊取消?