您的位置:首页 > 编程语言 > C语言/C++

在Qtcreator下cmake工程文件及使用Qt制作PCL C++ GUI

2014-09-09 18:04 1291 查看

在cmake下工程文件及使用Qt制作PCL
C++ GUI

写在前面的话:

         转载本人文章时请贴上链接,尊重你我的劳动成果。

文章中有任何问题,请留言说明,我一定回复并检查,捣乱者勿扰,有更好的解决方案我们也可以交流分享。

对于看文章时遇到的疑问,请看底部Q & A,后续想到了会考虑再增加。

 

名词解释:

GUI:顾名思义,graphic Userinterface,用户图形界面。

QT:有两层含义,一个是QTlib库,就像我们已经很熟悉的boost库一样,PCL官网已经提供了下载链接,或者也可以直接在Qt官网进行下载http://qt-project.org/downloads#qt-lib

除此之外,还需要安装一个新的IDE:qtcreator,功能就像Myeclipse和VS一样。

PCL Point Cloud Library 点云数据库。http://www.pclcn.org/或者http://www.pointclouds.org/

 

前一段时间,因为需要为PCL程序制作一个GUI界面,PCL官方的介绍里说要用到Qt这个库。现在将自己制作过程中遇到的一些问题总结一下,并提供解决方案,希望可以方便后来者。

首先要感谢一下Github的Logrus先生贡献的源码https://gist.github.com/Logrus/9988524

基于这个源码我比较容易的实现了在Qt——GUI下实现pcl_viewer的显示。



大家可以看到这个CMakeLists文件比我们之前在PCL官网接触到的文件多了一个Qt的路径,哦,我把源码中的4改成4.8了,但这是无关紧要的事情。

要注意的有以下几点:

1,对这个CMakeLists文件进行cmake时,不能直接使用cmake软件,否则会出现编译错误: cannot find Qt4, 或者:the Qt4 is not suitable关于如何使用Qtcreator编译生成解决方案文件,我下面会介绍。

2,按照作者的提示:cmake出的解决方案必须放在一个叫作build的文件夹中,请看pclwindow.cpp的第二行,否则生成的解决方案会出现运行出错。http://stackoverflow.com/questions/16065984/embedding-pcl-viewer-on-a-qt-gui-main-window

 

1 Qtcreator编译环境配置:

打开已经安装好的qtcreator:

1工具->选项->构建和运行:

CMake:设置cmake.exe路径。



Qt Versions:设置Qt(我们所安装的Qtlib下的qmake.exe)路径。



构建套件(Kit):设置编译器及Qt版本(这个很重要,否则会出现找不到Qt或者Qt版本不合适的情况),我看到网上的介绍里普遍将这个编译器设为MinGW(gcc在windows下的编译器),这里不是很必要,如果大家还记得的话,我们当时是按照编译器如(vs2010 32B)来选择PCL库编译或者安装的,所以这里的编译器要和我们计算机本身开发PCL时用的编译器保持一致,否则会出现无法找到PCL1.7.1.



2工具->选项->版本控制

至于版本控制,本人还没有研究。

 

配置好了环境接下来开始qtcreator调用cmake.exe,同时使用QT库生成我们需要的解决方案。

2 生成解决方案

文件->打开文件或项目,选择我们的CMakeLists.txt文件打开(把要编译的cpph文件和这个放在一个文件夹中,命名为source,方便!)



接下来这个参数应该和我们的命令行参数是一个道理,不用填,直接执行cmake,

Ok!perfect!

 


接下来,有了这个解决方案,我们就可以进行二次开发了。

3 UI界面设计

网上已经有了很多关于如何使用Qt制作UI的教程,有代码的,也有QT设计师的,就我个人而言,比较喜欢QT设计师,不只是因为它简单,而是因为我觉得这种所见即所得的设计模式才是真正适合UI设计的。

 

         首先看一下最后制作的成品。



那么如何制作这么一个界面呢?因为我在这过程中确实走了很多弯路,特意将一个比较顺利的流程写下来,以供大家参考。

 

1 PS一张背景图片

关于photoshop,本人用的是CS5,觉得功能已经够了,再高一点的版本电脑可能会吃不消,画布是1540 pixel*1000 pixel 120PPI 使用默认设置RGB色,我的电脑屏幕分辨率是1440*900pixel,所以整张背景图片预计也会画那么大,但是当时考虑到上,右各留100像素,可以再在顶部或者右边加一些东西,免得出什么问题。后来才知道ps中是可以将一组图层直接复制到另一个已经打开的psd中的(在图层面板里右键选择复制图层,对话框中目标文件选择我们已经打开的另一个目的文件就可以了),果然比较傻,大家可以选择使用第二种方法。

关于怎么画这张图我就不多说了,使用过PS的人都知道。要注意的是因为这是一张很规范的图,那么就要使用标尺和参考线。稍后会说把图标画的规范一点会有什么好处。

 

2 设计UI

打开用作者的文件编译好的工程,双击pclwindow.ui 打开设计师窗口



可以看到:1 控件窗口:跟C#的控件是一个意思;

                            2 显示窗口:所谓所见即所得,我们的设计好的UI界面会在这里显示;

                            3 动作窗口:控件的触发接口。

                            4 对象窗口:界面中所有控件的相互关系:父子继承关系,并列关系等;

                         5 属性窗口:类似于C#的Winform控件属性,不过这里稍有不同稍后会解释;

                            6 布局工具:用于管理控件的布局。

还有一个资源管理窗口,默认没有打开,如果喜欢打开这种设置的话,可以自行设置。

        

对于原来UI中用不到的控件可自行删除,在显示窗口或者对象窗口右击删除。因为QT中没有卸载控件选项,所以下面动作窗口的槽函数关系或者动作要手动(manual)删除;除此之外,pclwindow.h 中的槽函数声明

    privateslots:


     voidon_action_triggered();

voidon_action_2_triggered();

删掉,.cpp文件中的槽函数定义以及类中其他函数对槽函数的定义统统删掉。第一次使用Qtcreator时会发现无法用鼠标选中文字,更不用说ctrl+c ctrl+v了,解决方法:编辑->高级->去掉使用vim风格编辑前面的勾选。现在开始做我们自己的UI,有两种思路:a,我们将原来背景中控件图标全部隐藏,然后将背景图片赋给窗体背景,控件图标做成切片赋给控件Icon;b,将整幅图(连同已经布局好的控件图标)赋给窗体做为背景。然后将控件初始化为透明,点中(pressed)选中(hover)可以作为触发事件或者槽函数进行编辑,从而变为半透明某色。这里我用第二种方式。

 

原来作者的主窗口尺寸是796*471,我看着挺合适,因此这里没有改这个尺寸。

 

3 制作UI

1 背景



CentralWidget属性窗口styleSheet,点击右边的… 进入编辑样式表





添加资源->border-image,这里border-image相当于strech,而background-image相当于Till,后者会像铺地板一样按照尺寸在原始控件上铺设,而前者则会拉伸。

进入资源选择器,但现在这里面是空的。所以下面我们需要给该工程添加外部资源。




网上有很多资料,但是我们这里不一定适用?为什么?看了下面就知道了。

添加资源有两种方法。一种是直接添加系统提供的资源文件,然后选择所需图标。另一种是自己写资源文件。我用的是第一种。

文件->新建文件或项目, 文件和类->Qt资源文件。

新建Qt Resources file,将它还是放在source文件夹下,和CMakeLists.txt一起,命名为picture。其他默认。



可以看到我们创建之后的窗口是这样的,添加到项目默认是灰色的,不可用(diable)状态.



细心一点会发现当我们像在vs中那样,右击项目->添加新文件/添加现有文件也是灰色不可用状态;QT中不可以这样做么(不可以的话就不会有这个选项了,干嘛还多此一举把它做成灰色的?)?原因在于我们的工程文件是cmake出来的,世界上没有免费的午餐,这样做工程文件固然省去了很多麻烦的链接设置,但是问题是我们以后每次要新建文件(.h .cpp .qrc)时,都只能将它放在CMakeLists文件的旁边,重新cmake使用,其实也没有那么麻烦,只是把编译这道工序改成了cmake,Qt的设计者已经为我们考虑到了。右键项目文件(这里是qt_vtk_pcl)->执行CMake,将原始工程文件刷新即可(当然对已经存在在工程中的文件做修改就不用再次cmake了,只需要编译一下就可以了,点击左下角的那个小榔头)。

 

在正式进行cmake之前,这里还有一个问题,这里是QT的Cmake说明;链接https://qt-project.org/quarterly/view/using_cmake_to_build_qt_projects

原作者并没有在CMakeLists中给出qrc文件的编译代码,需要我们手动加上

 

准备工作已经到位,现在右键项目文件(这里是qt_vtk_pcl)->执行CMake,将原始工程文件刷新,可以看到现在的项目文件下多了一个picture.qrc。



 



我们最好先在文件夹source里新建一个文件夹,如images,然后将需要的图标文件放到其中。



在Qt Creator的menu.qrc文件中,我们点击Add下拉框,选择Add Prefix。我们可以将生成的/new/prefix前缀改为其他名字,/,当前目录。因为这个默认的/new/prefix是一个不存在的文件夹。然后再选择Add下拉框,选择Add Files。再弹出的对话框中,我们到新建的images文件夹下,将我们需要的图标文件添加过来。



添加完成后,我们在Qt Creator的文件菜单里选择保存所有文件选项,保存所做的更改。(注意:一定要先保存刚才的qrc文件,不然在资源管理器中可能看不见自己添加的资源!)



这时再centralWidget属性->stylesheet,添加资源->border-image,就可以看到我们的图标都在这里了。(注意:如果不显示,可以按一下上面的Reload按钮)



但是同时我们会发现我们的Widget控件也添加了这种背景,因为centralWidget是它的父控件(parent),所以我们为centralWidget添加的样式会用在它的所有子控件上。可以这样做,在样式表单框中直接填入以下代码。选框中的路径换为你直接设置borde-image时该框出现的文件路径。

来自http://blog.csdn.net/sbisyju/article/details/9071495



2 控件

按照前面说好的,要把所有控件与原始背景中的控件图标对齐。在QT设计师窗口中,没有控件的空白地方被认为是不可伸缩的,也就是说大小是固定的。那么程序运行后,当我们手动的拉缩窗口时,控件和背景图标必定是对不上的。为此QT中有了一个控件叫Spacers(间隔器),你也可以管它叫作弹簧。所有没有控件的空白区域填充上弹簧,就可以保证整个窗口等比例伸缩。

 

为了便于放置这些弹簧,也为了把窗口中本应水平/垂直对齐的控件对齐还要用到下面将要说到的一种控件和一种属性。

 

控件栏的Contaners(容器)控件组:

Frame:继承自Qwidget,具有最基本的Geometry属性。可以设置容器中控件组整体的位置大小(甚至我们本文中没有用到的背景控制)。

 

工具栏的布局组:

用于为容器添加相应属性,实现容器中控件的布局,注意只有将单独的布局管理改成容器+布局属性时,才能实现真正的布局管理,否则运行时,弹簧会丢失,也打不到管理的效果,因为只有在容器中我们才可以设置这个布局的位置以及大小。可以看看centralWidget的属性窗口,类型是QWidget,有一个附加属性Layout(horizontalLayout)。

 

 

水平布局,设置容器中控件组整体的上下左右边距,以及控件之间的水平间距。最终控件水平对齐。

 

 垂直布局,设置容器中控件组整体的上下左右边距,以及控件之间的垂直间距。最终控件垂直对齐。

 

 水平/垂直分裂器,还没有研究,不清楚。

 

 窗体布局,为主窗体生成一个管理它所有子控件的父容器,类似于这里的centralWidget。

 

栅格布局,设置容器中控件组整体的上下左右边距,以及控件之间的垂直间距与水平间距。最终控件按所设置的布局方案对齐,比较适合阶梯状的布局。

 

打破布局,删除容器上相应的布局属性。

 

从左边控件窗口栏的Containers拖动一个Frame到显示窗口,属性设置objectName:leftFrame,geometry:x 58  y 0 宽度 506 高度471,这个控件占据的位置应该是红色选框区域。关于这个位置我们也可以事先算出来,我建议算与拖相结合,毕竟直接拖动的尺寸并不精确。Y为0顶格  用ps画背景图时可以用参考线+尺寸显示的方式测出图上这个位置=x’(pixel)或者这个位置所占整幅图宽度的百分比,那么x=796*(x’/图片宽度)。宽度类似 
高度=主窗体高度。

 


 

为了让底部的三个控件水平对齐,再拖一个控件Containers的Frame到显示窗口。位置是蓝色选框的位置。ObjectName:frame。注意父子对应关系:leftFrame的Parent是centralWidget,frame的Parent是leftFrame。Geometry与前面的类似。这里x y的位置是frame相对于leftFrame的位置。





现在开始添加控件,从左边控件栏的Buttons拖动PushButton到frame中底下三个图标的位置。位置不用对齐,只要大概水平放置即可。

对象窗口 frame右键布局->水平布局(我这里栅格布局了,但是水平布局就可以了)。现在相当于为frame加了一个布局属性,就相当于玩游戏时某个武器多了一个技能点是一个道理。

Frame的布局属性设置,前面已经说过了,这里再说一遍,为了使所有控件即使在窗口拉缩时也能对齐,我的frame中也不能留白。所有边界距全为零。





把原来的显示pcl_viewer的widget拖到(在显示窗口中拖)leftframe下,设置geometry属性。剩余地方填充Vertical Spacer(黄色选框位置)





VerticalSpacer没有位置属性,但是有长宽属性,宽度即为前面算出来的506,高度可以通过前面已经算出来的其他控件的长度相加减得出。

现在记录下来leftFrame的直接各子控件的高度,verticalSpacer_3:48

Widget: 317 verticalSpacer_4:14 frame: 81 verticalSpacer_5:9.

对象窗口,leftFrame右键布局->垂直布局。布局属性设置如下图,看一下layoutStrech设置,如果没有这项设置,就无法实现控件与背景图标的等比例拉伸。

还有一点要说明,为了保证所有的控件能正常拉伸,控件属性的sizepolicy选项的水平垂直策略都是expanding。



同理制作rightFrame,绿色选框区域。







接下来用Horizontal Spacer填充剩余空白区域->淡蓝色选框区域



记录蓝红蓝绿蓝这五块各自的宽度。

在对象窗口,centralWidget右键->布局->水平布局,设置布局属性



 



再看一看是否所有的父子关系都已正确对应。



3 初始化控件

我们为控件设置的属性,就是它的默认初始状态。这里将所有pushButton的初始设为透明。



将根对象(这里是Pclwindow)的最小尺寸设为我们创建这个UI时的尺寸,防止用户将窗口缩放的过小时出现控件错位。



 

4 Q & A

1 Containers中有那么多容器控件,为什么我偏偏选择了Frame?

答:这是因为Frame没有边框,符合我的要求:只是把它当做一个容器使用,没有任何装饰效果,透明最好,之前用的是GroupBox,效果并没有这么好。

 

2 frame容器中控件组与容器上下左右边距全为0可以做到,但是控件之间怎么处理?比如rightFrame的下面那组控件的垂直间距,明显不为0,怎么处理?

答:关于这个我也尝试过将控件间垂直边距设为1,但是结果并不是很理想,运行时,窗口拉大,控件会出现错位,所以这个边距也必须为0,控件的高度做的适当大点,只要别有重叠部分,应该不会影响最后的运行效果。

 

3 运行时窗口缩放到比创建UI时更小时,控件出现严重错位怎么办?

答:关于这个请看初始化控件,将根对象(这里是Pclwindow)的最小尺寸设为我们创建这个UI时的尺寸,防止用户将窗口缩放的过小时出现控件错位。注意这个并不影响窗口本身的最小化功能,还是可以最小化的。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息