QT基础七、用纯代码编写界面
终于迎来了界面开发的实战环节!今天我们将通过纯代码的方式,亲手打造一个界面。如果你对 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_OBJECT
public:
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; // 创建水平布局1
hLayout1->addWidget(chkBoxUnderLine); // 将下划线复选框添加到水平布局1
hLayout1->addWidget(chkBoxItalic); // 将斜体复选框添加到水平布局1
hLayout1->addWidget(chkBoxBold); // 将粗体复选框添加到水平布局1
// 创建颜色相关的单选按钮
rBtnBlack = new QRadioButton("黑色"); // 黑色单选按钮
rBtnBlack->setChecked(true); //默认黑色单选已选上
rBtnRed = new QRadioButton("红色"); // 红色单选按钮
rBtnGreen = new QRadioButton("绿色"); // 绿色单选按钮
// 创建水平布局2,并将颜色相关的单选按钮添加到该布局中
hLayout2 = new QHBoxLayout; // 创建水平布局2
hLayout2->addWidget(rBtnBlack); // 将黑色单选按钮添加到水平布局2
hLayout2->addWidget(rBtnRed); // 将红色单选按钮添加到水平布局2
hLayout2->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; // 创建水平布局3
hLayout3->addWidget(btnOk); // 将确认按钮添加到水平布局3
hLayout3->addWidget(btnCancel); // 将取消按钮添加到水平布局3
hLayout3->addStretch(); // 添加一个可拉伸的空间,使按钮靠左对齐
hLayout3->addWidget(btnClose); // 将关闭按钮添加到水平布局3
vLayout = 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_OBJECT
public:
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(); //将文本转换为QString
auto 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_OBJECT
public:
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; // 创建水平布局1
hLayout1->addWidget(chkBoxUnderLine); // 将下划线复选框添加到水平布局1
hLayout1->addWidget(chkBoxItalic); // 将斜体复选框添加到水平布局1
hLayout1->addWidget(chkBoxBold); // 将粗体复选框添加到水平布局1
// 创建颜色相关的单选按钮
rBtnBlack = new QRadioButton("黑色"); // 黑色单选按钮
rBtnBlack->setChecked(true); //默认黑色单选已选上
rBtnRed = new QRadioButton("红色"); // 红色单选按钮
rBtnGreen = new QRadioButton("绿色"); // 绿色单选按钮
// 创建水平布局2,并将颜色相关的单选按钮添加到该布局中
hLayout2 = new QHBoxLayout; // 创建水平布局2
hLayout2->addWidget(rBtnBlack); // 将黑色单选按钮添加到水平布局2
hLayout2->addWidget(rBtnRed); // 将红色单选按钮添加到水平布局2
hLayout2->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; // 创建水平布局3
hLayout3->addWidget(btnOk); // 将确认按钮添加到水平布局3
hLayout3->addWidget(btnCancel); // 将取消按钮添加到水平布局3
hLayout3->addStretch(); // 添加一个可拉伸的空间,使按钮靠左对齐
hLayout3->addWidget(btnClose); // 将关闭按钮添加到水平布局3
vLayout = 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(); //将文本转换为QString
auto 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、运行结果
点击确认
点击取消