终于迎来了界面开发的实战环节!今天我们将通过纯代码的方式,亲手打造一个界面。如果你对 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、运行结果
点击确认
点击取消