一.界面设计的三种方式
1.使用界面设计器
开发效率最高,可以进行拖件即可。
但是有的界面效果实现不了。
2.纯代码界面设计
最为强大,可以灵活自如的操控
但是开发效率低
3.混合界面设计
前两种结合生下的孩子,你们的优点都到我这里了。
今天我们先来讲讲纯代码的方式。
二.纯代码进行界面设计
1.代码界面设计的总思路
- 首先确定需要那些组件
- 然后定义好组件
- 初始化组件
- 用布局将组件添加到窗口
- 定义槽函数
- 关联槽函数
- 实现槽函数
2.创建项目
项目简单,选择对话框即可
因为纯代码,不需要ui文件,使用取消掉Generate form
其他都跟原来的一样。
3.设计草图
因为我们要知道我们需要那些组件,所以说一般我们会先设计一个草图,知道自己需要用那些组件。
从草图中,我们可以知道,我们需要复选框 单选框 文本框 按钮
4.添加组件指针
我们知道了自己需要的,现在就开始进行添加
首先需要加相应组件的头文件。
在dialog.h中
#include <QCheckBox> //复选框 #include <QRadioButton>//单选框 #include <QPlainTextEdit>//纯文本编辑器 #include <QPushButton>//按钮
然后在private里面把组件添加成成员数据
private: QCheckBox*chkBoxBold; //粗体复选框 QCheckBox*chkBoxUnderLine;//下划线 QCheckBox*chkBoxItalic;//斜体 QRadioButton*rBtnRed;//红色单选框 QRadioButton*rBtnBlack;//黑色 QRadioButton*rBtnGreen;//绿色 QPlainTextEdit*txtEdit;//纯文本编辑器 QPushButton*btnOK;//确定按钮 QPushButton*btnCancel;//取消 QPushButton*btnExit;//退出
这样就添加完成了,变量名要自己能看懂哦
5.初始化组件指针
可以直接在Dialog的构造函数中进行初始化,但是会显的代码杂乱无章。
因此我们可以统一定义一个接口来进行初始化。
在private里定义一个void initUI()的接口
在Dialog的构造函数进行调用。
然后现在在initUI函数里面做具体实现:
在dialog.cpp中
void Dialog::initUI() { chkBoxBold=new QCheckBox; chkBoxItalic=new QCheckBox; chkBoxUnderLine=new QCheckBox; rBtnRed=new QRadioButton; rBtnBlack=new QRadioButton; rBtnGreen=new QRadioButton; txtEdit=new QPlainTextEdit; btnOK=new QPushButton; btnCancel=new QPushButton; btnExit=new QPushButton; }
6.添加组件到窗口
其实添加组件到窗口有一个接口,就是setGenmetry()
但是这样的进行添加的话,有两大缺点
首先,你需要设置具体的位置
其次,你如果对窗口进行拉升是不会自动适应的
因此我们要学会使用布局
①水平布局
可以先理解为,将在同一行的多个组件放在一起,就是在一个布局里。
水平布局的头文件
#include <QHBoxLayout>
创建一个水平布局,将同一行的组件添加到布局中
void Dialog::initUI() { chkBoxBold=new QCheckBox; chkBoxItalic=new QCheckBox; chkBoxUnderLine=new QCheckBox; rBtnRed=new QRadioButton; rBtnBlack=new QRadioButton; rBtnGreen=new QRadioButton; txtEdit=new QPlainTextEdit; btnOK=new QPushButton; btnCancel=new QPushButton; btnExit=new QPushButton; QHBoxLayout *HLay1=new QHBoxLayout; HLay1->addWidget(chkBoxUnderLine); HLay1->addWidget(chkBoxItalic); HLay1->addWidget(chkBoxBold); QHBoxLayout *HLay2=new QHBoxLayout; HLay2->addWidget(rBtnBlack); HLay2->addWidget(rBtnRed); HLay2->addWidget(rBtnGreen); QHBoxLayout *HLay3=new QHBoxLayout; HLay3->addWidget(btnOK); HLay3->addWidget(btnCancel); HLay3->addWidget(btnExit); }
addWidget的意思是添加组件的意思。
注意添加组件顺序是从左到右的。
这里就把组件都添加到水平布局上面了
②垂直布局
接下来开始垂直布局,就是将从上到下的布局或者组件添加到垂直的布局中。
QVBoxLayout*VLay=new QVBoxLayout; VLay->addLayout(HLay1); VLay->addLayout(HLay2); VLay->addWidget(txtEdit); VLay->addLayout(HLay3);
然后将垂直布局添加到对话窗口中就可以进行显示了
setLayout(VLay);
运行结果:
③细节点
效果图很明显没有对应的文字,不用慌,我们在初始化的时候配上文字。
void Dialog::initUI() { chkBoxBold=new QCheckBox("粗体"); chkBoxItalic=new QCheckBox("斜体"); chkBoxUnderLine=new QCheckBox("下划线"); rBtnRed=new QRadioButton("红色"); rBtnBlack=new QRadioButton("黑色"); rBtnGreen=new QRadioButton("绿色"); txtEdit=new QPlainTextEdit; btnOK=new QPushButton("确定"); btnCancel=new QPushButton("取消"); btnExit=new QPushButton("退出"); QHBoxLayout *HLay1=new QHBoxLayout; HLay1->addWidget(chkBoxUnderLine); HLay1->addWidget(chkBoxItalic); HLay1->addWidget(chkBoxBold); QHBoxLayout *HLay2=new QHBoxLayout; HLay2->addWidget(rBtnBlack); HLay2->addWidget(rBtnRed); HLay2->addWidget(rBtnGreen); QHBoxLayout *HLay3=new QHBoxLayout; HLay3->addWidget(btnOK); HLay3->addWidget(btnCancel); HLay3->addWidget(btnExit); QVBoxLayout*VLay=new QVBoxLayout; VLay->addLayout(HLay1); VLay->addLayout(HLay2); VLay->addWidget(txtEdit); VLay->addLayout(HLay3); setLayout(VLay); }
运行结果:
布局的好处就是我可以拉大窗口,组件跟着变
如果水平某个地方你希望空着,不均匀分布。那可以在水平布局里面添加一个拉升器。
在按钮的水平布局里面第三个位置添加了一个拉升器。
QHBoxLayout *HLay3=new QHBoxLayout; HLay3->addWidget(btnOK); HLay3->addWidget(btnCancel); HLay3->addStretch();//添加拉升器 HLay3->addWidget(btnExit);
运行效果:
是不是很神奇,哈哈哈!
还可以设置默认文本
txtEdit=new QPlainTextEdit; txtEdit->setPlainText("给我点点关注,我也给你点点关注");
运行结果:
单选框也可以被默认选中。
rBtnBlack=new QRadioButton("黑色"); rBtnBlack->setChecked(true);//黑色默认被选中
运行结果:
OK,现在咱们的界面就设计好了,开始我们的功能具体实现了!
7.定义槽函数
public slots: void onChkBoxBold(bool checked); void onChkBoxUnderLine(bool checked); void onChkBoxItalic(bool checked); void setTxtColor();
因为复选框可以打开也可以关闭所以说,我们要接受一个bool值,来确定当前的状态。
对于单选框我们只能选一个,功能都是相同的,所以可以只用定义一个槽函数即可。
对于按钮,已经内置了可以用的槽函数,就不需要定义。
8.初始化信号槽
对信号槽的初始化,就是信号槽的关联。
我们也统一定义一个函数(initSignalSlots)去统一关联。
void Dialog::initSignalSlots() { //关联复选框 connect(chkBoxBold,SIGNAL(clicked(bool)),this,SLOT(onChkBoxBold(bool))); connect(chkBoxItalic,SIGNAL(clicked(bool)),this,SLOT(onChkBoxItalic(bool))); connect(chkBoxUnderLine,SIGNAL(clicked(bool)),this,SLOT(onChkBoxUnderLine(bool))); //关联单选框 connect(rBtnRed,SIGNAL(clicked()),this,SLOT(setTxtColor())); connect(rBtnBlack,SIGNAL(clicked()),this,SLOT(setTxtColor())); connect(rBtnGreen,SIGNAL(clicked()),this,SLOT(setTxtColor())); //关联按钮 connect(btnOK,SIGNAL(clicked()),this,SLOT(close())); connect(btnCancel,SIGNAL(clicked()),this,SLOT(close())); connect(btnExit,SIGNAL(clicked()),this,SLOT(close())); }
记得要在dialog的构造函数中进行调用。
9.实现槽函数
ok,现在框架都搭好了,开始实现我们的槽函数了。
对于复选框我们要先拿到文本的字体,然后再继续修改,然后又设置回去。
#include <QPalette> ... void Dialog::onChkBoxBold(bool checked) { QFont font=txtEdit->font();//取出文本的字体 font.setBold(checked);//根据checked来设置字体为粗体 txtEdit->setFont(font);//将字体设回到文本中 } void Dialog::onChkBoxUnderLine(bool checked) { QFont font=txtEdit->font(); font.setUnderline(checked); txtEdit->setFont(font); } void Dialog::onChkBoxItalic(bool checked) { QFont font=txtEdit->font(); font.setItalic(checked); txtEdit->setFont(font); } void Dialog::setTxtColor() { QPalette palette=txtEdit->palette();//拿到文本的调色板 //判断哪一个按钮被点击 if(rBtnRed->isChecked()) { palette.setColor(QPalette::Text,Qt::red); } else if(rBtnBlack->isChecked()) { palette.setColor(QPalette::Text,Qt::black); } else if(rBtnGreen->isChecked()) { palette.setColor(QPalette::Text,Qt::green); } //将调色板设回文本 txtEdit->setPalette(palette); }
颜色的实现思路差不多,先用palette取出调色板,然后设置,Text是对文本有效
记得有调色板要头文件哦!
运行结果:
完美呀,哈哈哈,终于完成了,你也试试看吧!
10.总结一下:
用纯代码来设计界面是,我们是要遵循一个逻辑循序的,这样你的代码就会条理清晰,且可维护性高。
其次就是组件和布局的应用也是界面设计的重点。
你看不到希望,只是因为你才刚刚开始,仅此而已,加油!