Qt教程-Qt Creator中定制GUI程序(界面布局)

绝大多数的GUI界面都是直接由各种控件组合堆叠而成的,有的程序界面设计的优良能从容面对各种状况(比如界面拉伸,多语言扩展),也有一些界面本身就不太友好(比如界面文字显示不全,控件不对齐),那么想设计一个友好的界面我们就必须得用到界面布局这样的功能。这里我们介绍一下Qt中界面布局的使用方法。
在Qt中进行界面布局有2种方法,第一种绝对定位,第二种布局定位。我们首先来看第一种。我们平常使用的界面大多都是长方形或者正方形,我们可以把界面想象成大棋盘,棋盘上的每一个点都有固定的坐标,我们把控件放到这些坐标点上就能堆叠出我们想要的样子。这样的布局方法就是绝对定位,控件在固定的位置不会变动。绝对定位很方便,把空间拖到想要放的地方就行了,但是很明显,如果窗体的大小做出了改变控件并不会因此做出任何响应,我们可能会因此看到界面上出现大片的留白。我们也可以通过设置窗体属性限制用户改变窗口的大小,但这并不一定是个好方法。当然我们也可以自己拦截窗口的消息事件通过自己的代码动态的确定各种控件的位置和大小,但是很显然,这样太麻烦了。
这种时候我们我们就在Qt中就可以使用布局定位的方法使得控件能够自动的拉伸各种控件或者改变控件的各种坐标。
我们先看一张示意图。

界面布局中通常是这样设计的,这里有几种布局器可以使用。
QHBoxLayout:按照水平方向从左到右布局。
QVBoxLayout:按照竖直方向从上到下布局。
QGridLayout:在一个网格中进行布局,类似于excel中单元格那样。
QFormLayout:按照表格布局,每一行前面是一段文本,文本后面跟随一个组件(通常是输入框)。
我们可以在窗口布局中嵌入其他的布局,最后形成我们看到的界面。
我们可以先创建自己的布局控件放入布局中做出自己想要的样子。这个时候可能运行起来还是不能自动缩放布局的,我们还得为窗口创建布局,并且得确保所有控件都处于可缩放的状态。
窗口创建布局:

此外所有需要缩放的控件都需要设置SizePolicy属性。这个属性来控制布局管理中的控件的尺寸自适应方式。
有下面几种属性可以选择。
Fixed:控件不能放大或者缩小,控件的大小就是它的sizeHint。
Minimum:控件的sizeHint为控件的最小尺寸。控件不能小于这个sizeHint,但是可以放大。
Maximum:控件的sizeHint为控件的最大尺寸,控件不能放大,但是可以缩小到它的最小的允许尺寸。
Expandint:控件可以自行增大或者缩小。
注:sizeHint(布局管理中的控件默认尺寸,如果控件不在布局管理中就为无效的值)

我们都选择为Expandint即可实现自适应窗口大小。
通过Qt Creator我们可以很方便的实现可视化的界面设计,当然如果有特别的需要也可以通过手工编写代码的方式来完成界面布局。
Qt文档中给出的例子如下:

该例中创建了5个Button控件,然后把控件都加入QHBoxLayout,最后形成的效果就是5个按钮按照顺序水平方向排列。

Qt教程-Qt Creator中定制GUI程序(国际化多语言)

作为一个设计良好的Qt程序,支持多国语言是显而易见的需求,毕竟需要照顾到的用户人群也许是不分国界的,那么如何使得程序拥有多语言则是一个很大的问题,这里我们继续使用之前的例子来演示多语言的处理。
要设计多语言,我们首先向工程中加入ts文件。
如下图所示:

也就是向pro文件加入

这里加入DISTFILES是给项目增加了其他文件的的意思,个人推荐加上这样方便点,当然也可以不加。
之后需要使用Qt Creator中的更新翻译菜单,更新翻译文件。
如下图所示:

这里注意.ts文件不要自己手工创建,如果创建了一个空文件再更新翻译,可能会收到类似这样的错误“zh_cn.ts:1:0: 文档过早的结束。”
更新完毕之后我们选择启动Qt语言家(Qt Linguist)对字符进行翻译。

启动Qt语言家后我们需要首先选择语言文件对应的是哪种语言。
如下图所示:

随后我们就能看到翻译界面,选择需要翻译的短语,然后填上相应的翻译内容最后保存即可。

这里注意的是,部分控件使用了html代码来控制格式内容,如果我们想保持和之前一致的显示风格,则需要连同html代码一起复制。这里我们为了演示效果,并没有留下html代码。
翻译完成后选择菜单的发布翻译即可,最后会生成一个qm文件。
为了让程序加载我们的翻译文件,我们需要在代码里面增加加载翻译的代码。
这里我们直接修改主函数,让程序根据系统设置的国家自动选择语言。

通过这些代码,如果系统设置为中国地区,程序在启动时会加载启动目录下的zh_cn.qm这个文件。这里需要注意的是,编译产生的可执行文件往往不在源代码目录,所以需要自行复制qm文件到可执行文件所在的目录。
最后运行效果如图

工程源代码下载地址:
https://www.exvs.org/wp-content/uploads/public/Qt_Tutorial/MainWindow_language_609C0483.7z

Qt教程-Qt Creator中定制GUI程序(添加多界面)

这一节我们将为之前创建的MainWindow工程添加第二个界面实现多窗口的演示。
首先打开之前的MainWindow工程,然后选择新建一个界面类,如下图所示:

之后我们可以选择一个Dialog界面模板,Dialog界面和之前创建的MainWindow有一点区别,默认是不会生成菜单栏,工具栏,状态栏这些的,一般Dialog界面用来做二级窗口。

选择以后我们继续下一步。

选择好类名,继续下一步。

最后完成创建。
之后我们打开aboutdialog.ui就可以对第二个界面进行设计了。

这里我们使用了QLabel控件,QLabel的功能就是显示文字或者图片,使用起来非常的简单。
接着我们回到mainwindow.ui的设计界面,为之前创建的关于菜单添加一个处理函数。

这里我们选择triggered信号,triggered信号和clicked有点像,不同的是clicked只能在被点击时触发,而triggered不仅可以被点击触发还可以被快捷键等方式触发。点击OK后Qt Creator会帮我们创建这么一个槽函数。
如下图所示:

我们写好槽函数之后,直接编译运行然后点击菜单后就可以看到效果。
那么问题来了,我们并没有看到connect函数把槽和信号连接起来,为什么最后却执行成功了呢?
我们可以看到moc处理完成的.h文件中最后调用了QMetaObject::connectSlotsByName函数,这个函数的作用就在于,这个函数通过特定的槽函数名,来自动连接信号和槽,这样我们就不需要再手工调用connect函数来连接了。
函数将自动连接符合on_object名字_信号名()这样名字的槽函数。举个例子,ui里面加一个按钮,按钮的object名字定位为 pushButton, 然后我们定义一个槽,叫 void on_pushButton_clicked();这样这个槽函数将会被自动连接。
最后我们编译运行后可以点击菜单查看效果,效果如下图所示。

Qt教程-导航目录(index)

基于Qt开发点什么并不是什么新鲜事,但是国内网络上大部分资料已经相对有些久远了,对于初学者来说这样的资料并不是很友好,所以我在这里想尝试重新编纂一份Qt的教程尽量的满足大家的需要。
算是给自己开个坑,也算强迫自己,希望这些文章对读者会有所帮助。由于文章众多,发布时间也不能完全按照顺序处理,故这里我新建一个导航目录。本系列文章我会按照推荐的阅读顺序在此罗列。

1、Qt介绍(暂无)
2、Qt开发环境安装与配置(暂无)
3、Hello World
4、信号槽
5、自定义信号槽和信号槽的实现
6、使用Qt Creator创建GUI程序
7、使用Qt Creator创建GUI程序02(添加图标,菜单,工具栏,状态栏)
8、Qt Creator中定制GUI程序03(添加多界面)
9、Qt Creator中定制GUI程序04(国际化多语言)
10、Qt Creator中定制GUI程序05(界面布局)
11、Qt Creator开发实例-计算器

未完待续
最后更新时间:2017/04/07

Qt教程-Hello World

这个系列的教程将直接基于Qt 5.8进行开发,目标是最终掌握使用Qt开发GUI和Qt各种常用模块的使用。
作为Qt的教程尝试第一个开发的 Qt 项目那必然是Hello World。
在正确的安装Qt和Qt Creator后,我们打开Qt Creator,新建一个projec(工程项目)。
如下图所示:
选择新建菜单。

传统的桌面GUI程序我们选择Qt Widgets Application就可以了。

输入项目名hello_world.

选择编译套件。

这里我们选择不创建UI。

最后完成创建。

创建完成后我们从项目中删除默认创建的其他文件,只留下main.cpp。

之后我们修改main.cpp的代码为

随后我们可以通过构建菜单进行构建,运行。
编译运行后可观察到运行结果。如下图所示:

这个程序很短,我们说明一下。
对于GUI程序,引入QApplication是必不可少的,QApplication这个对象为GUI引入了事件循环等一系列的东西。所以通常在main函数都要先创建一个QApplication对象(对于非GUI程序是可能是创建QCoreApplication)。之后我们定义了一个QLabel对象,QLabel对象是标签对象,通常用来显示一些内容。紧接着我们使用了resize成员对label对象的大小进行了更改,这里我们更改成长300,宽100,单位是像素。随后我们使用show函数来显示界面。最后我们调用exec启动事件循环,这样我们就能看到图上的运行结果了。事件循环会一直保持运行,exec函数也不会返回,会一直等待到窗口关闭然后进行返回,所以当窗口关闭时程序将正常退出。