1.前言
上一章,我们介绍了如何用Qt库来开发界面程序,以及如何使用VS开发Qt程序。
而一旦涉及到了窗口编程,那么其中最重要的一个环节便是控件。
所以本章,我就将带大家过一遍Qt里面常用的控件,方便以后使用。
项目就是上一章节在VS里面建的。
当然,如果你更喜欢使用Qtcreator
,这也是没问题的,与VS相比较来看,其实除了项目文件配置方面不同以外,其它方面没有任何区别。
2.Push Button
这个控件前面章节中我们已经讲过了,不过这里还是稍微总结一下。
它所属类为QPushButton
,这是可以方便我们查帮助文档的。
它最重要且最常用的信号函数是:clicked
,用于响应用户点击。
最常使用的属性是下面两个:
当然如果你想要改变这个按钮的样式,那么styleSheet
属性肯定也是很有用的,Qt里面几乎所有控件都会有这个属性,后面不再多提。
objectName
:对象名,即这个控件的名字,方便以后在代码中使用这个控件。text
:即按钮上面显示的文字。
最常用的代码片段即为:
connect(按钮变量名的地址,&QPushButton::clicked,其它对象,其它对象的槽函数);
如我在VS里面,默认设置创建的Qt项目,响应Qt按钮点击的代码为:
connect(ui.pb_test, &QPushButton::clicked, this, &QtWidgetTest::OnBtnClick);
ui.pb_test
:按钮的名字,即前面的objectName
&QPushButton::clicked
:取点击信号函数的地址this
:因为我是在窗口类的使用它,所以this
,即代表这个窗口类。&QtWidgetTest::OnBtnClick
:我自己在这个窗口类中定义的一个函数:
3.Line Edit
除了按钮以外,最常用的一个控件应该就是Line Edit
了,看它的名字也能知道,它用于输入一行文本的:
比如输入账号,输入密码,输入链接等等,不需要换行接收用户输入的地方,基本都可以使用它
它所属类为:QLineEdit
,可用于在帮助文档中查看它有哪些函数,哪些信号与槽,方便开发更高级的功能
它最常用的属性一般是以下两个:
控件名我们就不说了,下面这个placeholderText
就很高级了,MFC里面可没有这玩意。
它的作用就是在编辑框里面显示提示信息,如下:
一般使用它信号的地方比较少,我们所需要的主要功能就是获取它内部的文本,可以通过它的函数text
即可获取其中的输入内容。
QString str=ui.le_test->text();
这里le_test
为我给这个控件改的名字
当然你也可以通过函数setText
,更改里面的文本:
ui.le_test->setText("测试一下");
4.Label
然后很常用的就是单纯显示文字内容了,这就是Label
控件,如其名,就是一个标签,可以任意贴上文字:
其所属类为:QLabel
它常用的属性就是显示的文字:
当然如果你想要在代码中任意改变它的显示文字,可以通过其函数setText
,使用方法与上面的Line Edit
一致。
5.Radio Button
接着是单选框按钮,这个也比较常见,就是让用户在几个特定的选项中,选择其中一个,比如性别等。
它所属类为:QRadioButton
还是老样子,更改其两个属性:
然后接下来,我们就需要在代码中进行操作了。
因为这是单选框,即在一组中,只能选择其中一个,所以我们就得将上面两个单选框添加到一个组中。
首先需要添加头文件:
#include<qbuttongroup.h>
或:
#include<QButtonGroup>
这两个的效果都是一样的,不过在VS中,后者没有智能提示,使用起来会很不方便,但前者有智能提示。
然后,创建一个按钮组对象,最后,调用函数addButton
,即可将两个按钮添加进一个组:
QButtonGroup* sex = new QButtonGroup(this);
sex->addButton(ui.rb_man);
sex->addButton(ui.rb_wuman);
然后运行程序,你就发现只能选择两个中的其中一个了。
注意上方的代码,我使用的new
的方式,即在堆中申请对象,为了的是避免这个函数结束了之后,这个组对象就被清除了。
但这样做你会发现一个问题,即申请的这个内存空间,我却没有任何一个地方去释放它?这不就是内存泄露吗?
这就是Qt的另一个独到之处了,即对象树的概念,比如上方的代码:
QButtonGroup* sex = new QButtonGroup(this);
用new
实例化一个对象,其构造函数我却传入的this
,这是什么意思?有什么用?
形象的来说,上面就相当于做了一件事:实例化的sex
按钮组对象,找了一个父亲为this
,至于什么清除内存(delete
)的事情,那就交给父亲做了,我不管了!
也就是说,当采用这种方式new
出的对象,我们就不用考虑内存泄漏的事情了,当这个父对象结束生命时,这个子类也就跟着父类一起被释放了。
Qt里面几乎所有类,都有这个构造函数,所以以后你在Qt编程中,看到的几乎都是用new
的方式进行实例化对象。
然后回到这里这个控件,我们可能还需要默认选择一个按钮,就可以调用按钮的setChecked
函数。
ui.rb_man->setChecked(true);
运行后,就会默认选择该按钮:
紧接着,当用户点击提交按钮时,我们就还需要判断一下用户选择了哪个按钮:
就可以通过按钮的函数isChecked
来进行判断即可,被选中了该函数返回true
,否则返回false
ui.rb_man->isChecked();
当然以上是一种最简单且朴实的方法,如果该组中的按钮太多,就会很不方便,所以就可以通过Qt的信号与槽机制进行简化。
首先我们得保存住按钮组变量:
然乎,在添加按钮函数这里,我们可以通过第二个参数,给按钮赋予一个ID:
sex = new QButtonGroup(this);
sex->addButton(ui.rb_man,0);
sex->addButton(ui.rb_wuman,1);
ui.rb_man->setChecked(true);
接着,我们再写一个响应函数,即槽函数,然后将上面两个按钮的点击事件,都连接到该函数上:
connect(ui.rb_man, &QRadioButton::clicked, this, &QtWidgetTest::OnBtnClick);
connect(ui.rb_wuman, &QRadioButton::clicked, this, &QtWidgetTest::OnBtnClick);
最后,我们就可以在槽函数中,通过保存的组变量,获取当前选中的按钮ID:
void QtWidgetTest::OnBtnClick()
{
switch (sex->checkedId()) {
case 0:
break;
case 1:
break;
default:
break;
}
}
上面的代码,就是通过获取的ID值,再交给switch
语句,进行分别处理即可。
6.check box
说完单选框,接下来的就是复选框了,它所属类为:QCheckBox
还是老样子,改下面两个属性,其它两个控件一样,不再赘述:
复选框用起来就会比单选框要简单一下,毕竟可以多选,也就是说不用必须去分组了。
最简单的方法当然还是用函数isChecked
函数,来挨个判断这些按钮是否被选中:
if (ui.cb_lan->isChecked()) {
}
if (ui.cb_pai->isChecked()) {
}
if (ui.cb_zu->isChecked()) {
}
当然,也可以采用更高级点的办法,那就是使用信号和槽,它的一个常用信号就是stateChanged
即当该复选框的状态发生了变化时,就会发送这个信号。
注意,它是一个带参的信号:
所以我们写对应的槽函数时,要和它保持一致:
然后就可以根据信号发生时,根据这个槽函数传入的值,做出相应的反应。
注意这里是用的Qt命名空间中的枚举变量作的比较。
该信号函数的说明里面有:
通过以上的实验我们可以看到,使用信号于槽的方式会非常繁琐,因为那意味着你有多少个复选框,你就需要多少个槽函数。
优点也很明显,就是可以根据用户点击,程序可以实时做出反应。
而上方第一种比较简洁的那种方式,就需要用户再点击一个其它的提交按钮,确认按钮之类的,来触发我们的代码。