ITK VTK QT VS CMAKE 问题记录

有关于自己 ITK VTK QT 混合开发时候遇到问题记录下来,会长期更新。

 

首先相信自己作为初学者,遇到的问题一定不是个例,先自己搜,谷歌百度CSDN中文英文关键词,运行库官网,example,耐心看,这是解决一切问题的基础,很重要。

 

什么是CMAKE?

CMAKE是管理项目的编译工具,帮你配置好一切,包括第三方库的路径,依赖项等等,可以说如果要写一些复杂的项目用Cmake来管理工程是非常推荐的。Cmake的配置依靠的是CmakeList.txt文件,cmake 有自己一套语法,有学习成本但是掌握了就会很好用。

基本操作很简单,Configure配置,然后generate生成,再open project就可以编程运行了

 

什么是项目?

以下个人理解:项目就是字面意思,面向对象的编程往往需要很多杂七杂八的库,各种库需要调用,所以你写的每一个程序,都应该叫项目,编程书上写个std::cout<<"hello world"<<

是没有实战意义的。你不能写个cxx文件,用vs打开就debug编译,是行不通的。

 

什么是dll?系统环境变量?

一般有这个问题肯定是运行程序时候,说少了XXX.dll不能运行,dll就是动态链接库,从字面上看他是个库还有个链接功能,里面有一些写好的函数,这样程序运行的时候就可以调用。当程序需要某个dll的时候,会从系统环境变量下PATH这个条目下往下找(有优先级,从path找我记得是优先级最低的),PATH这个条目下都是设置好的一些路径,里面有不同软件的dll文件,如果你的程序找不到,比如说qt的某个dll或者vtk的某个dll,那就是你没有配置他的路径到系统环境变量里,程序自然找不到。很多教程有一个懒人方法就是缺啥补啥,比如xx.dll 就把这个dll搬运到自己的运行目录里。这样可以解决问题,但是换个项目的时候,同样的问题会继续出现,所以我个人建议配置好path。

 

搬运dll到system32这个目录解决问题?

强烈反对这个解决方案,因为会造成很多麻烦。因为debug和release所需要的dll不同,但是他们名字是一样的,比如都叫vtkxxx.dll(qt好一些,debug的dll会有个d作为标识),程序调用的时候只看名字,只有他们调用后才发现错了,会造成程序崩溃无法运行。更具体表现是,你把某个dll扔到了system32里,并且也配置了正确的系统环境变量,但是一运行程序就出错,或者debug和release有一个会编译不通过,因为需要某个dll时,系统会先去system32文件夹里搜索,system32文件夹优先级高,(这个也就是为什么能解决问题),程序找到了对应名字的dll就不找了,无论是不是正确的。所以说只有正确配置系统环境变量和写好CMAKELIST让cmake自动配置好你所需要的库等才能一劳永逸,不要随意手动移动dll文件。

ITK VTK 的安装?

网上教程非常多,多看几篇就懂了,从官网下的是他的源码,你不能直接用,需要通过CMAKE编译成可以运行的库你才能调用它。有两个比较基础但是让人迷糊的点

首先用CMake编译源码后用vs打开itk、vtk的sln文件,此时选择编译类型debug或者release进行具体生成,推荐release,并且自己之后的工程也只能在release模式下编译

 

另外CMake编译时的Prefix那一项是指在vs生成时如果额外执行了Install项,那么你的itk/vtk库也会复制一份到prefix指定的目录。当别的工程需要ITK VTK目录时,可以指定prefix指向路径下include文件夹下ITK/VTK版本也可以指向源码编译后的地址。

 

我想实现图像某个功能,但我不知道用什么算法?

看example,搜关键词,看guide book

 

不允许指针指向不完整的类类型

在指针指向赋值或者获取值的时候有时会发生,编译错误的红色下划线不在那个没定义的类上,而是出现在最前面的指针上

原因:类名写错了。或者忘记加相应的头文件,尤其是你以为这是属于一个很基础的类,之前在别的程序用过,其实并不是。

自己遇到的实例是GetFirstRenderer()这个方法我以为在vtkRender.h里,再不济也在vtkRenderWindowInteractor.h或者vtkRenderWindow.h里结果发现其实在vtkRendererCollection.h里

 

QT和vtk itk的结合/给简陋的ITK VTK设计个GUI

单纯写一个vtk或者ITK的程序的话是没有图形界面的,也就是说如果输入参数只能通过命令提示符来传入参数,这很不方便,或者在程序内输入比如cin 让用户输入读取文件或者保存文件地址,这样也很不直接。设计个GUI来给程序套上,便于交互。因为ITKVTK对qt的支持非常良好,所以在这我选用QT这个软件来设计。

首先要去了解Qt信号与槽的机制,这有点点像VTK的observer的设计,掌握大概后再把qt安装好就可以操作了。

关于QT的安装没啥好说的,教程很多,值得注意的一点是用cmake管理项目时QT的dir 应为C:/Qt/5.14.1/msvc2017_64/lib/cmake/Qt5 也就是指向到这一级目录,这里面有qt的camke config,这样CMAKE才会知道其他的东西比如core 在哪里

假设自己一切都安装完成了,一般有两个选择,在Qt编译器也就是qt creater下完成所有代码工作,用qt自带的qmake管理工程,再其次是用qt生成所需的文件后用camke管理工程,这样可以用别的编译器,我自己用的vs写代码并且之前一直用cmake,所以用的第二种。

qt生成五个文件:两个cpp文件一个是主函数,另一个是主函数下调用的执行函数,一个执行函数的头文件,还有就是关键的UI文件,最后是一个cmakelist文件后我们用cmake编译一下就可以生成项目。

因为qt itk vtk一起用那么少不了库的链接,这里希望自己保持上面说的 正确设置 的操作,不要随意搬动dll文件。这样只需要在cmakelist中加上比如find itk这样的语句(参考纯itk/vtk工程)就可以用了,也就是把vtk工程和qt工程的cmake文件动脑子拼在一起就是我们所需的cmake文件

 

打开工程后和往常一样编程即可,但是要注意不要再主函数多写什么东西,面向对象的编程意识要强一些,这有好处。

不过用VS编写UI的时候有一个,就是可以用QT designer来拖拽控件来设计Ui,但是他不会自动更新你的操作,每次编辑完你的UI除了保存之外还要右键你的项目重新扫描解决方案 这样ui文件对应的ui_xxxxx.h文件才会编译,你新加进去的控件对象才能实例化。如果不管用就重新生成解决方案最大的那个项目,即ALL_BUILD上面那个。

另外我学到了一个编程习惯或者说技巧就是怎么把槽函数中生成的变量,从槽函数中拿出来变成全局变量,当然可以设置返回值但是有点奇怪,所以我们用指针,思路就是在头文件即这个窗口类里面定义一个全局的空指针/对象。然后在槽函数的实现函数里,通过this调用,因为槽函数也是隶属于这个类的,所以这个this就会把我们定义过的那个所需的指针/对象拿出来,要赋值要修改就随便你了,

具体实践比如就是把输入的path这个字符串怎么传递到reader里。

首先在头文件里声明一个字符串 a

在“打开文件”这个槽函数中声明一个字符串b用来存放路径

在槽函数中用this->a把A调用出来给他赋值

如果有stdstring和qstring不兼容的情况又tostdstring这个方法可以解决

这样一来a就有了b的值并且是全局的,这样后续在别的槽函数里的reader需要path的时候只需要把b传递过去即可。

另外qdebug这个东西是要有自己的单独头文件的,别忘了include

#########2020.0502更新

前天把项目完成了,有一些qt心得,qt交互的功能实现基本都是基于信号与槽。

槽函数之间的互动问题的解决,即我理解为比如A按钮触发后的行为有很多种,要根据B按钮的状态决定,那怎么获知B按钮的状态呢,那肯定要通过同一个实例化的指针获取B按钮状态,比如AB按钮(本质是槽函数,且为同一个mainwindow实例的槽函数)都在Mainwindow下,即可通过this指针传递获取信息。

但是开发项目中我遇到的一个问题是,A按钮(槽函数)中的某个交互行为的定义是通过一个非qt类(vtk的command类)来定义的,然后这个非qt类需要获知mainwindow类下某个成员状态(比如布尔类型),即这个类和mainwindow没有任何关系,这时候在这个非qt类里如果实例化一个mainwindow类成员或者指针,虽然他可以调用mainwindow类下所有方法和成员,但是这个对象是新的,并非之前的this指针,也就是无法获取之前在主窗口下实例化的B类对象下某个成员的状态,这时候我的解决办法是,在这个非qt类的类中写一个mainwindow类指针成员,并且再写一个setter方法来接收指针,让这个mainwindow指针成员指向接收来的指针,即指针指向另一个指针。这个A按钮槽函数实例化这个非qt类对象时,调用非qt对象下的setter方法传入this指针,这样在这个非qt类下的那个之前预设的mainwindow类的指针即为A按钮槽函数里的this指针,这样调用这个非qt类实例的时候,就会自动根据mainwindow类的他所需的成员状态来决定实现哪种行为。

 

关于程序打包

原来release模式过了以后的exe文件不能在任何电脑都能运行,前提是要有同样的运行库环境,写个hello world基本所有的win平台电脑都可以运行,因为这个程序所调用的dll(如果有调用的话)也是系统基础自带的,比如可能是一些关于输入输出流的dll。但是像这种调用了三个库的程序,尤其是因为这三个库作为开发库一般电脑上没有,所以不能直接运行。需要运行时在他同级目录下带有他运行所需要的dll文件(因为写代码编译时用的动态编译,如果是静态编译好像出来的exe里封装了所需运行库所以会很大),这时候就涉及到程序打包的问题,即把执行文件exe和所依赖的dll文件封装在一起,可以简单粗暴的用压缩包封装,也可以用一些插件或者第三方软件做成安装文件,像一个正常发行的软件一样。关于程序所依赖的dll一般需要命令或者软件查询,在此推荐denpendices这个软件可以查询exe文件运行的话需要啥dll。qt自带的那个dll查询软件更是神器,自动查询并且可以打包到目录下,但是只能查询打包qt自己的dll文件,我这样的多个库开发的就还要把除了qt库的dll文件手动找到,目前自己还没有找到一个能查询又能自动打包提取的一步到位的软件,有的话会更新。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值