使用对话框和Qt设计师来实现一个相当简单的小游戏。同时将通过这个程序来看布局的隐藏和显示是如何来影响窗口界面的变化的。
新建一个Qt项目,把Qt Creator默认给的mainwindow.h、mainwindow.cpp、mainwindow.ui三个文件删除掉,这里我们只创建一个对话框。虽然也会创建出类似的这3个文件。
先来设计一下界面,在Qt设计师中新建一个【Dialog without Buttons】。
我放入这几个部件:
各个部件对象的名称:
在GuessNumberDialog对象,也就是整个对话框,它的【windowTitle】属性,也就是标题,就是【猜数字】。
在Qt设计师中在部件中使用中文,不需要担心会出现乱码,至少我还是没有遇到过的。
其它部件的属性没怎么改动,有的话也就是他们的名称了。
对于QSpinBox和QcomboBox的对象,在写代码中会去改一下它的属性。
在【最大值】和【最小值】标签,后面有个很奇怪的东西,"&M"和"&N"是什么?其实我是想让这2个标签拥有快捷键的功能。但是,一般来讲,给标签设置快捷键似乎也没什么用处吧,因为他们一般是不可编辑不可按的,不像编辑框、按钮那样。
在2.1创建对话框那一篇文章里曾经在一个标签部件上使用过一个函数,setBuddy。这个函数的参数是另一个部件……
所以在Qt设计师中,要使标签具有快捷键功能,并且能够通过这个快捷键定位到另外一个部件上去,除了在这个标签上写上"&M"或"&N",还需要再一个步骤。
点击工具栏的【编辑伙伴】按钮。
此时鼠标可以移动到【最大值】标签上,左键按住,然后鼠标移动到要相关联的部件上,自然是移到【maxValueSpinBox】这个微调框部件上了。
成功后,你就会惊讶地发现,"&M"变成了"M",也就是变身快捷键了。
同理,【最小值】标签也可以这样子做。
设置完成【伙伴】之后,点击工具栏的【编辑窗口部件】按钮。回到编辑的编辑状态。
现在来对这些部件做布局。
左键点击【输入数字范围】这个群组框部件,会将它选中:
然后点击工具栏的【栅格布局】图标。
你将看到,【输入数字范围】群组框部件里面的部件已经自动排列。
但是,排列之后,"开始游戏"的位置比较奇怪。
上一节也是有提过的,栅格布局相当于QGridLayout,就是相当于把各个部件放在一个表格的不同单元格中一样。可能比较好理解吧……一个部件可以连续占多个单元格,不管是横还是竖方向上的占用。
我们需要对部件摆放成一个大致的布局,我可以把"开始游戏"按钮在栅格布局之后,重新调整它的大小。
不过这个按钮似乎有些长了,看着感觉怪怪的,我想把它放在中间该怎么做呢?
可以使用一个起到"占位符"作用的部件:【Spacers】
它可以将"多余"的空间全部占用,使得部件都能够调整成最佳的大小,而不需要将部件再调整它的大小去占用多余空间,有损"美观"。
要将已经布局好的一组部件打破,只需要点击一下这个布局内的任一一处,然后点击工具栏上的【打破布局】按钮。
打破布局之后,我们在"开始游戏"按钮左边和右边都加上【Horizontal Spacer】。
然后再次使用栅格布局。
不过这样会增大部件占用的空间。
同理,【猜数字】群组框部件也可以同样使用栅格布局。
最后,单击对话框内的空白地方,再按【栅格布局】按钮。
然后再点击【调整大小】按钮。
将对话框调整到最佳的大小。
到此,这个界面就做完了。保存这个文件。
在Qt Creator中新建一个项目。
右键【项目名称】,点击【添加新文件】,选择【C++ Class】,写上类名,然后就完成创建。我创建的类叫【GameDialog】。
将ui文件添加到这个项目中。
在【gamedialog.h】中,代码如下:
头文件基本就没什么要说明的了。
然后是源文件,先看构造函数:
第6、7行:设置QString和tr()函数的字符显示编码。设置了UTF-8之后,中文就能够正常显示了。
第12行:重新调整对话框的大小。将猜数字群组框隐藏之后,窗口大小还不会随之自动改变,可以自己手动调用adjustSize来调整窗口大小到最佳状态。
用到的函数:void QWidget::adjustSize ()
函数的说明:调整部件的大小以适应其内容。在例子中,部件是指整个对话框。
第14行:将部件的信号和槽的连接全部定义在一个函数中,比较方面查看。
play()函数,如果点击了"开始游戏"按钮,则调用这个槽函数:
第20行:检测最大值和最小值的有效性。
第25行:qrand()函数是一个随机数函数,差不多相当于rand()函数吧。设置一个最小值和最大值范围内的随机数。
第27行:设置组合框中的选项。
selectNumber()函数,当组合框当前索引值发生改变之后,就会调用这个槽函数:
第40行:组合框的索引从0开始,而0是"请选择数字"这一选项,所以如果当前索引是0,则直接返回。
第43行:断开信号和槽的连接,这可以防止在initComboBox()函数重新设置选项时而触发了组合框当前索引改变的信号。
第47行:检测值,如果与m_num这个值相同,就猜对了,否则猜错了。
第59行:tr()函数,它是一个将字符串内的文本翻译成其他语言的标记,可以用于具有多语言版本的程序中。
只要程序中有其它语言的翻译文件,就可以将当前字符串内的文本显示成其它语言的翻译版本。这个是随便自己的咯,也可以不用加tr()函数。而是直接一个字符串。翻译文件在以后也会说的。
tr()函数返回的是QString类型。QString中有一个arg()函数。它用于将QString字符串里的"%1"这个符号替换成arg()函数中的数值。"%1"相当于是一个占位符,与printf()函数中的"%d、%s、%f"等占位符相同道理。
arg()函数返回的是字符串第一个"%n"被替换之后的QString类型字符串。
如果需要替换多个,可以使用"%n",然后后面再加上n个arg()函数。
例如:
用到的函数:QString QString::arg ( const QString & a, int fieldWidth = 0, const QChar & fillChar = QLatin1Char( ' ' ) ) const
函数的说明:返回此字符串的副本,用字符串a来替换一个数值最小的位置标记,位置标记如:%1,%2,……,%99。
当然,arg()函数有多个函数重载版本,支持不同类型变量数值来替换字符串。
第72行:猜错之后,最大值或者最小值将重新设置。组合框的选项也将重新设置。
initConnect()函数和initComboBox()函数:
第94行:在添加完选项之后,将当前选择设置到索引为0的项。也就是"请选择数字"。
第96行:连接信号和槽,当组合框的当前索引发生改变时,调用GameDialog类中的selectNumber()槽。
checkValid()函数和checkValue()函数:
都是好理解的2个函数。
最后,main.cpp中的代码:
这就不需要再做说明咯。
运行结果:
OK,基本就是这样子~~~