Qt VTK软件开发问题学习记录

1. 0x00000000000000处有未经处理的异样

程序运行时出现下面问题肯定是内存错误,但到底是数组越界(数组边界溢出)指针错误链接库问题......就需要进一步调试(debug)。

Qt VTK软件开发问题学习记录 

链接:赛码在线开始系统:http://oj.acmcoder.com/QA/

在线编程题总是报运行错误,是什么情况?

运行错误一般都是数组越界非法访问野指针乱访问空指针乱访问等情况造成代码奔溃

 

2. error LNK2019

LINK :error LNK2019:无法解析的外部符号 "__declspec(dllimport)...《进阶》p11

这类问题与库在具体环境下的配置不完善所造成的库的加载错误有关,解决方法如下:

方法1自动配置CMakeLists.txt脚本文件、CMake配置及生成新的工程)

网上有很多资料讲到MFC环境下开发VTK程序时,需要手动在Visual Studio中设置VTK的包含路径和liib库路径。这种方法对于一般用户来说比较复杂,每次新建工程时,都要查找和设置这些库,既费时费力,又不利于程序的移植(例如换到另外一台计算机,如果VTK编译路径不一致,就找不到库)。因此推荐读者使用CMake来管理工程(如下),因为仅仅几行脚本代码就可以实现VTK库在具体环境下的配置,而且便于程序移植

//设置方法bin(dll)——>include(h)——>lib(lib)

Step1①设置编译好的动态库目录(.dllbin文件夹路径到系统path环境变量中。(似乎不用,见问题3

Step2修改CMakeLists.txt文件MODULE_INCLUDE_DIRECTORIES.h)包含目录MODULE_TARGET_LIBRARIES.lib)库目录两个变量的值

Step3然后重新配置(configure)、生成(generate)新的工程

参见:http://blog.163.com/[email protected]/blog/static/1582209320169711559384/

方法2手动配置path环境变量—VTK的动态库目录路径(bin)、VTK的包含目录路径(include)、VTKlib库目录路径(lib)—VTK的具体所需的库文件)

注意:

.a 文件肯定是静态链接库对吧?

我记得 .lib文件不一定是静态链接库文件,还有可能是dll的地址文件

//设置方法(版本1bin(dll)——>include(h)——>lib(lib)

Step1设置编译好的①动态库目录(.dllbin文件夹路径到系统path环境变量中。

直接在工程中修改项目属性,步骤如下:

Step2VC++目录——>常规——>②包含目录(.hVTKinclude文件夹路径

Step3VC++目录——>常规——>③库目录(.libVTKlib文件夹路径

Step4链接器——>输入——>④附加依赖项(.lib具体的所有的依赖的(需要链接的)VTK库文件lib

//设置方法(版本2bin(dll)——>include(h)——>lib(lib)

Step1设置编译好的①动态库目录(.dllbin文件夹路径到系统path环境变量中。

直接在工程中修改项目属性,步骤如下:

Step2C/C++——>常规——>②附加包含目录(.hVTKinclude文件夹路径

Step3链接器——>常规——>③附加库目录(.libVTKlib文件夹路径

Step4链接器——>输入——>④附加依赖项(.lib具体的所有的依赖的(需要链接的)VTK库文件lib

也有可能是下面两种方式选择不对造成的:

#include <vtkAutoInit.h>   

VTK_MODULE_INIT(vtkRenderingOpenGL2);

VTK_MODULE_INIT(vtkInteractionStyle);

VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);

#include <vtkAutoInit.h>   

VTK_MODULE_INIT(vtkRenderingOpenGL);

VTK_MODULE_INIT(vtkInteractionStyle);

VTK_MODULE_INIT(vtkRenderingVolumeOpenGL);

 

3. 计算机中丢失xxx.dll

这是运行时错误,是动态库加载问题,是因为无法链接到动态库造成的(计算机中丢失XXX.dll),如果工程项目的属性设置确保正确,采用如下4种方式解决:

解决方式

序号

具体操作

缺点

全部复制

将提示无法找到的dll文件全部复制到工程的Debug或者Release目录下(复制时要注意编译的VTK(需要复制的)是Debug版本还是Release版本,如果复制版本不对,可能会出现其他不可预知的错误!)

该方法要求每新建一个工程,程序运行之间都需要复制所提示的dll文件,明显比较烦琐。

将提示无法找到的dll文件全部复制到Windows系统目录下,即C:\Windows\System32Win64系统最好还需复制到C:\Windows\SysWOW64,确保无误。

这种方法同样有个问题——假如计算机中的VTK版本升级或者改成其它版本,VTK版本切换时相对比较麻烦。

配置系统环境变量

编译好的动态库(.dllbin文件夹路径到系统path环境变量中即可!

 

使用CMake管理和构建与QtMFCFLTKGUI开发工具整合的VTK应用程序

可以考虑在工程的CMakeLists.txt文件里添加一些命令构建、生成工程时系统的PATH环境变量加载进来,使得工程启动之前就加载这些环境变量程序运行时就不会有动态库加载错误的问题

工程通过CMakeconfigure(配置)以及generate(生成)以后,即可生成StartVS_debug.batStartVS_release.bat两个脚本文件。如果需要编译、运行Debug版本的工程,可双击StartVS_debug.bat文件打开对应的工程,Release版本的工程也类似。一旦按这种方式打开对应的工程,就不用担心出现类似“无法加载xxxx.dll文件”的错误。

 

 

 

采用上面四种方式可以解决动态库加载问题的原因是:

动态编译的程序在启动时,会搜索程序所在的目录以及系统环境变量PATH所列的目录,如果这些目录有该程序所需要的动态库文件,就加载它们;如果没有,就会出现无法加载相应动态库的错误。

Qt VTK软件开发问题学习记录 

 

4. fatal error LNK1104

LINK : fatal error LNK1104: 无法打开文件D:\VTK-8.8\VTK-res\lib\vtkInteractionStyle-8.0.lib

  LNK1104无法打开文件E:\opencv3.1\opencv\build\x64\vc14\lib.obj

这类为问题还是与类库的加载有关,解决方法如下:

①首先确保该文件的确为库文件,即文件在类库中的确存在!如果不存在则需重新编译库;

②查看该项目属性中:VC++目录——>③库目录(.lib)lib文件夹路径是否正确(为该库文件所在文件夹路径),不正确改为正确路径。

链接:****贴:http://blog.****.net/zyjj_99/article/details/39394477

fatal error LNK1104: 无法打开文件“***.lib“ 解决方法

       我们在做一个工程时,工程内可能包括几个项目每个项目负责一个子功能最后在主项目中调用很多时候这些项目都是以DLL的方式生成,那么我们在主项目调用DLL时,需要配置项目选项,如果配置不当,就会报错:fatal error LNK1104: 无法打开文件“***.lib“ 

VS2010为例,配置方法是:

方法①:

1. 选则”Project“->"Property"->C/C++选项-->”General“-->Additional Include Directories,这个里面输入dll对应的.h头文件所在的目录目的是在主项目中调用#include<***.h>时能够根据这个目录找到头文件,否则就会报错,找不到头文件

2.选则”Project“->"Property"->Linker选项-->"General"--Additional Library Directories,这里面输入dll所在的目录,一般情况下,同一个工程的所有DLL项目输出都是在工程的默认输入目录,所有可以这儿输入:$(OutDir);

3..选则”Project“->"Property"->Linker选项-->”Addtional Dependencies“,这里就是输入lib文件名,多个的话用分号隔开

经过三个配置,就可以顺利调用dll的接口方法

方法②:

另外除了这种配置的方法之外,还可以在文件中动态的输入,如:#pragma comment(lib, "../Debug/maker_qr_encoder.lib")也可以达到效果

 

 

5. Error: no override found for 'vtkPolyDataMapper'()(vtk几何渲染和体渲染底层都需要使用OpenGL

Qt VTK软件开发问题学习记录 

Generic Warning: In D:\VTK\VTK-8.0.0-src\VTK-8.0.0\Rendering\Core\vtkPolyDataMapper.cxx, line 28

Error: no override found for 'vtkPolyDataMapper'.

或者:

Generic Warning: In D:\VTK\VTK8.0.0-src\VTK-8.0.0\Rendering\Core\vtkRenderer.cxx, line 52

Error: no override found for 'vtkRenderer'.

或者:

Generic Warning: In D:\VTK\VTK8.0.0-src\VTK-8.0.0\Rendering\Core\vtkRenderWindow.cxx, line 40

Error: no override found for 'vtkRenderWindow'.

Qt VTK软件开发问题学习记录 

解决方法参见:收藏夹c++ - no override found for 'vtkPolyDataMapper' - Stack Overflow

https://*.com/questions/18642155/no-override-found-for-vtkpolydatamapper

CMake配置VTK就可以看出:VTK渲染底层(后端)使用的是OpenGL/OpenGL2VTK渲染包括几何渲染和体渲染)。

VTK_RENDERING_BACKENDOpenGL/OpenGL2

注:VTK_渲染_底层(后端)

Qt VTK软件开发问题学习记录 

在代码的最开始增加:

#include "vtkAutoInit.h" 

VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2)

VTK_MODULE_INIT(vtkRenderingOpenGL2);// VTK was built with vtkRenderingOpenGL2

VTK_MODULE_INIT(vtkInteractionStyle);

或者

#include "vtkAutoInit.h" 

VTK_MODULE_INIT(vtkRenderingVolumeOpenGL)

VTK_MODULE_INIT(vtkRenderingOpenGL);// VTK was built with vtkRenderingOpenGL

VTK_MODULE_INIT(vtkInteractionStyle);

 

6. 问题同1(显卡不支持?)

Qt VTK软件开发问题学习记录 

Warning: In D:\VTK\VTK-8.0.0-src\VTK-8.0.0\Rendering\OpenGL2\vtkOpenGLRenderWindow.cxx, line 835

vtkWin32OpenGLRenderWindow (00570EF8): VTK is designed to work with OpenGL version 3.2 but it appears it has been given a context that does not support 3.2. VTK will run in a compatibility mode designed to work with earlier versions of OpenGL but some features may not work.

 Qt VTK软件开发问题学习记录

这是由于VTK只支持英伟达的显卡。

1.如果出现这种问题,首先确保你有独立显卡(英伟达的)。

2.找开显卡设置面板,将全局设置那一栏下的首先图形处理器设为高性能NVDIA处理器。

来源参见:http://blog.****.net/bai_dreamer/article/details/52934470

 

7. error LNK1112

error LNK1112: module machine type 'X86' conflicts with target machine type 'x64'

模块计算机类型’X86’与目标计算机类型’x64’冲突

模块计算机类型:编译模块库时所用的计算机类型

目标计算机类型:编译目标程序所用的计算机类型

编译器编译依赖于其他函数库的程序时采用的版本应该与与这些函数库编译时采用的版本一致!

Qt VTK软件开发问题学习记录 

8. 警告 C4819

警告

C4819 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为Unicode 格式以防止数据丢失

(编译源文件

C:\Users\pianmo\Desktop\Materials of  Software Development\Softwares\opencv-3.2.0 Sources(Pack included)\modules\video\src\compat_video.cpp) opencv_world C:\Users\pianmo\Desktop\Materials of  Software Development\Softwares\opencv-3.2.0 Sources(Pack included)\modules\core\include\opencv2\core\utility.hpp 1

解决具体步骤::

点击错误列表选项卡-点击代码字段下方的错误序号C4819-转跳到浏览器中连接到微软的MSDN帮助文档中:

链接:

https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=ZH-CN&k=k(C4819)&rd=true

帮助文档信息:

编译器警告(等级 1)C4819

Visual Studio 2015

其他版本

若要了解有关 Visual Studio 2017 RC 的最新文档,请参阅 Visual Studio 2017 RC 文档

该文件包含不能在当前代码页(数字)中表示的字符。 以 Unicode 格式保存该文件防止数据丢失。

在具有不能表示文件中所有字符的代码页的系统上编译 ANSI 源文件时,出现 C4819。

若要解决 C4819,请以 Unicode 格式保存该文件。 在 Visual Studio 中,选择文件高级保存选项 在高级保存选项对话框框中,选择可表示该文件中的所有字符编码 — 例如,utf-8,然后选择确定

 Qt VTK软件开发问题学习记录

 

 

9. 使环境变量生效,有两种方式:

 

方式1:设置环境变量后重启电脑。

方式2:打开DOS终端(Windows + r,输入命令:cmd), 如果是设置环境变量“PATH”,则在修改完成后,在DOS窗口命令行中输入:set PATH=C:,然后关闭DOS窗口。再次打开DOS窗口,输入:echo %PATH% ,可以发现“我的电脑”->“属性”->“高级”->“环境变量”中设置的PATH 值已经生效。(DOS窗口中的环境变量只是Windows环境变量的一个副本,通过对副本的修改可以引发Windows环境变量的刷新,所以只是环境变量刷新了一次,不用担心DOS窗口中的修改会使得系统环境变量的值变成了”C:”)。

 

10. vtkTextActor (008116F0)

ERROR: In D:\VTK\VTK-8.0.0-src\VTK-8.0.0\Rendering\Core\vtkTextActor.cxx, line 113

vtkTextActor (008116F0): Failed getting the TextRenderer instance!

 

解决办法:在头文件中加入VTK_MODULE_INIT(vtkRenderingFreeType)

百度:VTK_MODULE_INIT(vtkRenderingFreeType),可见到其他相关问题解决办法。

 

11. Qt预言家Liguist的使用

来源:http://blog.chinaunix.net/uid-20901038-id-1832058.html

Qt显示中文最简单的方法就是利用国际化工具linguist简单步骤如下

①修改*.pro文件,添加TRANSLATIONS = *.ts

②执行lupdate *.pro命令,生成*.ts文件

③用linguist工具 翻译

④执行lrelease *.pro命令,生成*.qm文件

⑤在源文件添加代码,载入*.qm

    QTranslator *translator = new QTranslator;

    translator->load("*.qm");

app.installTranslator(translator);

来源:http://www.360doc.com/content/14/0328/14/3300331_364436093.shtml

Qt项目要实现多语言,必须做两件事

①确保每一个用户可见字符串都使用了tr()函数;

②在应用程序启动的时候,使用QTranslator类对象载入一个翻译文件(.qm)。

具体使用步骤见来源。

 

我的经验:

要使用tr()函数,有两种方式:(1QObject::tr()[static]静态函数;2)在类声明的需要使用元对象编译系统的内容前添加Q_OBJECT

注意:在声明中添加Q_OBJECT宏的类,即是需要使用元对象编译系统的类,这样的类必须直接或间接继承自QObject

注意:半路添加Q_OBJECT宏后,必须重新执行qmake、构建、调试运行完整流程  当然,你也可以随便修改一下 .pro 文件,哪怕是添加或删除一个空格或空行什么的都可以。使得qmake可以自动运行。来源:http://bbs.****.net/topics/390942343

关于Qt的元对象系统参见:http://www.kuqin.com/qtdocument/metaobjects.html

 

12. QString转换为char *

方法一:QString转换为能打印显示的char*的步骤四步

QString转换为具体编码格式的字符串QString::toUtf8()/toLocal8Bit()/toStdString()/....;

具体编码格式字符串转换为char*QString::toUtf8()/toLocal8Bit()/toStdString()::data();//QString::toStdString::c_str();

③使用char*数据构造QByteArray字节数组对象:QByteArray qba=QString::toUtf8()::data();

④将QByteArray数据转换为能打印显示的char*数据QByteArray::data();

方法二:(三步,略去方法一第②步)

QString::toUtf8()/toLocal8Bit();

QByteArray ba = QString::toUtf8()/toLocal8Bit();不用再将具体编码格式字符串转换为char *

注意:不适用于QString::toStdString!错误如下:

 Qt VTK软件开发问题学习记录

const char *fileName_str = QByteArray::data();

13. QVTKWidget集成到Qt Designer/Qt Creator

Step1:正确安装Qt,出现文件夹D:\Qt\5.9.1\msvc2015\plugins\designerD:\Qt\Tools\QtCreator\bin\plugins\designer

Step2CMake编译支持QtVTK库,出现文件夹D:\VTK\VTK8.0.0-res\Release\plugins\designer,其中生成有QVTKWidgetPlugin.dll文件(注意:一定需要是release版本的!)

Step3:将生成的release版本的QVTKWidgetPlugin.dll文件拷贝到Step1中的两个文件夹中。

注意:

Step3中拷贝的文件必须是release版本VTK库,否则拷贝后会无法打开Qt Designer/Qt Creator

Step3只需拷贝QVTKWidgetPlugin.dll一个文件即可,无需像网上教程一样拷贝QVTKWidgetPlugin.lib和其它lib/dll文件

Step1D:\Qt\5.9.1\msvc2015\plugins\designer文件夹对应Qt DesignerD:\Qt\Tools\QtCreator\bin\plugins\designer文件夹对应Qt Creator如果不需要联合使用,可以只拷贝QVTKWidgetPlugin.dll文件到对应文件夹,一般都需要拷贝QVTKWidgetPlugin.dll文件到两个文件夹

 

14. Qt大型项目的多工程多模块中的子工程间引用问题/依赖问题

背景:****——Qtpro配置多个子工程/子模块:

http://blog.****.net/liang19890820/article/details/51775652

详见****——Qt多工程多目录的编译案例:

http://blog.****.net/libaineu2004/article/details/23625441

目前的只有一个方法,即上面文档中的方法:

1)一个大型项目中只有一个app工程,其他工程都为库工程。

app工程引用其他动态或静态链接库工程;

②动态链接库工程中可以再引用其它动态或静态链接库工程。

③静态链接库工程中不能再引用其它动态或静态链接库工程。

2)待发现......

拓展:Qt创建并使用共享库:****——Qt之创建并使用共享库:
http://blog.sina.com.cn/s/blog_a6fb6cc90102vsdn.html

关于共享库的创建网上有很多教程,当然,我还是喜欢看官方的文档,可参考:How to create a library with Qt and use it in an application.

    什么是共享库呢?其实就是我们常说的动态链接库。

    动态链接库和静态链接库的区别又是什么?

 

区别一:

动态链接就是把调用函数所在的DLL和调用函数在文件中的位置等信息链接进主程序,程序运行的时候再从DLL中寻找相应函数代码,因此需要相应DLL文件的支持。 静态链接库是把LIB文件中用到的函数代码直接链接进主程序,程序运行时不再需要其它库文件。

动态链接库和静态链接库都是共享代码的方式,如果采用静态链接库,LIB中的指令全部被直接包含在最终生成的EXE 文件中。但是若使用DLL,该DLL不必被包含在最终EXE文件中,EXE文件执行时可以“动态”引用和卸载这个与EXE独立的DLL文件。

区别二:

动态链接库中可以再包含其它动态或静态链接库。

静态链接库中不能再包含其它动态或者静态链接库。

使用及发布:

    静态链接库,虽然效率高点,且发布简单,但可执行程序较大。。。

    动态链接库:相关联的库以DLL的形式引用,不被包含进可执行程序,发布不方便(需要将每一个DLL都添加到安装包中),但可执行程序较小。。。而且共享库的一个好处是可以动态加载,也就是说,如果涉及到软件升级,那么简单的替换掉相应的DLL就行,不需要重新安装整个程序。

15. 获取函数运行结果的三种方法

①返回值(通过函数返回值的方式获取函数运行结果)

②传址调用(通过指针类型函数参数传址调用函数,传入的指针变量指向函数运行结果)

③传引用调用(通过引用类型函数参数传引用调用函数,传入的引用变量指向函数运行结果)

上层变量始终都要在上层声明,只是有声明为成员变量还是函数局部变量的区别,通过上面三种方式都可获取其他函数运行结果,只是说直接传引用到下层去获取值是最好的一种方式。

如果这个上层变量(指针等类型)很有用的话,可在上层声明为成员变量,然后以参数引用方式传入下层函数,在下层函数内部被直接赋值或被下层变量赋值

注:传引用调用是一种常用的获取函数运行结果的方法,在公司中也是常用这种方法,而不采用返回值的方式

16. 类类型的函数返回值

 Qt VTK软件开发问题学习记录

类类型的函数返回值需返回一个对象实例,而不存在“空对象”的情况。

①如果需要返回一个值做判断,可返回以下几种类型:

BOOL[TRUE/FALSE],

int(float)[0/0],

指针类型[NULL/NULL]

而将函数运算结果(即需返回的对象实例)通过上面15问中的③传引用调用方式从下层对象传递到上层对象即可

②如果实在需要返回“空对象”,可以考虑以下做法:

返回一个类的对象实例,可以参考

vtkSmartPointer<vtkImageData> MyFunction()

{

    vtkSmartPointer<vtkImageData>myObject=vtkSmartPointer<vtkImageData>::New();

    return myObject;

}

自己new一个类对象默认构造函数初始化应该就是“空的对象”

 

注意:模板分为模板函数和模板类,模板函数实例化后为函数,模板类实例化后为vtkSmartPointer<T>智能指针也是一种模板类,其本质仍然是一种类,而不是指针,用类运算符重载重载了->运算符,使其能像指针一样使用而已。所以vtkSmartPointer<T>智能指针模板类实例化后也是一个对象实例作为函数返回值类型时不存在返回“空对象”的说法,只是说默认构造函数初始化应该就是“空的对象”。。

 

17. vtk渲染管线及其初始化

一、管线:

vtkSource->vtkFilter->vtkMapper->vtkActor->

vtkRenderer->vtkRenderWindow->vtkRenderWindowInteractor

这部分的渲染管线在视图初始化时构造,因为对于一个视图而言仅需一个显示窗口和一个绘制器,所以该部分仅需要构造一次就为整个视图的显示做好了准备工作

②这部分的渲染管线将封装成该视图的成员函数

二、初始化:管线创建后一定要初始化才会起作用!

vtkRenderWindow()->Render();(如果有下面的操作,可省略)

vtkRenderWindow()->GetInteractor()->Initialize();

vtkRenderWindow()->GetInteractor()->Start();

三、特例

QVTKWidget控件设置完vtkRenderWindowvtkRenderer即可,不需要进行管线初始化

 

18. VTK确定相机的视图平面的三个因素

VTK相机位置、焦点位置和相机朝上方向三个因素确定了相机的实际方向,即确定相机的视图平面

注意:相机朝上方向必须与相机位置和焦点位置的连线(直线)垂直否则可能会报以下警告:重置朝上方向因为视图平面的法线是(与相机位置和焦点位置的连线)平行的

 Qt VTK软件开发问题学习记录

注意方向向量是一个相对量,代表所有位置的方向,不代表一个具体位置的方向,具体位置的方向该位置和方向向量两方面决定

renderer->ResetCamera();    //重新设定相机(只重设相机位置和焦点,不改变相机向上方向)

注意:重新设定相机函数vtkRenderer::ResetCamera()只重设相机位置和焦点,不改变相机向上方向

 

19. 智能指针

智能指针的引用计数是对某个智能指针所指的动态内存分配空间的引用计数,而不是对该智能指针的引用计数

智能指针是类模板,类模板实例化为模板类,类实例化为对象,所以智能指针类模板实例化后为模板类对象,模板类重载了间接成员访问运算符->,所以可以当作指针使用。

普通指针可以隐式构造智能指针(不能构造为智能指针的引用,因为引用就是别名,必须类型相同),但是智能指针不能隐式转换为普通指针,提示:“不能static_cast,可reinterpret_castC样式转换和函数转换”,实际使用vtkSmartPointer::GetPointer const函数转换就可从智能指针得到普通指针。

 

20. VTKImagePlaneWidget使用说明

原创 2016072613:24:02 1217

来源:http://blog.****.net/cfqcfqcfqcfqcfq/article/details/52033899

VTKImagePlaneWidget 是一个3D交互部件,用来重切图像数据。(3D widget for reslicing image data

作为交互部件,基类为vtkInteractorObserver,其工作在当前交互器风格下,即Widget通过交互器监听用户事件(也就是说,交互部件会比其他交互观察者优先地从交互器中截取自己所能响应的VTK事件并做出处理,对于不能响应的事件,该事件会继续由其他注册了的交互观察者vtkInteractorObserver的子类如vtkInteractorStyle响应处理)。因此要使用该部件,必须先调用SetInteractor()函数设置交互器。

可以通过SetCurrentRenderer()设置渲染器,默认情况下渲染器都会从你所设置的交互器中获取。

部件的核心功能是由vtkImageReslice类提供的,该类能够快速获取体数据的切片。通过获得该类的数据输出纹理映射管道上,可以获取其切面的纹理贴图

为了能够获取的切片的纹理贴图,需要通过setInputConnection()函数来给部件设置体数据此时体素的拾取功能才会被**。如果没有设置体数据,请调用SetTextureVisibility(int)函数关闭纹理映射

VTKImagePlaneWidget 样式如下图:

 Qt VTK软件开发问题学习记录  

 

  该部件主要通过鼠标来完成对部件的交互,具体操作如下:

 1)  按下鼠标中键(滚轮)+移动光标 用来控制部件方向和位置。

如图中4条蓝色的线将VTKImagePlaneWidget分为9个区域,其中将光标移到红色数字所代表的的区域,可以将切片沿着垂直于平面法向量的方向旋转;当把光标移到橘黄色光数字所代表的区域,可以改变平面法向量从而翻转整个平面;当把光标移动到center区域,可以沿着当前平面法向量的方向平移切片。

 2)按下鼠标左键+移动光标 可以拾取切片的坐标值和体素值(显示在渲染窗口的左下角)

当光标位于切片内,按下鼠标左键,会出现十字交叉线来锁定你所拾取的体素。

 3 ) 按下鼠标右键+移动光标 改变切片的窗位窗宽(显示在渲染窗口的左下角)。

 4Shift+鼠标中键  缩放切片

向上移动光标放大切片,向下移动光标缩小切片

 5Ctri+鼠标中键

当光标位于center区域,可以任意方向移动切片;当位于橘黄色数字所代表区域,可以拉伸或缩短该边界;当位于红色数字所代表的区域,可以拉伸或缩短该角所组成的边界

 

 常用的属性值设置函数:     

    //GetCursorProperty()->SetColor(0,1,0);//设置十指交叉线颜色

    //GetMarginProperty()->SetColor(0,1,1);//设置分界线的颜色

//GetPlaneProperty()->SetColor(0,0,1);//设置切片边框为蓝色(未选择状态)

//m_ImagePlaneWidget->GetPlaneProperty()->SetOpacity(1.0);//设置切片边框的不透明度

    //GetSelectedPlaneProperty()->SetColor(1,0,0);//设置切片边框为红色(选择状态)

//m_ImagePlaneWidget->GetSelectedPlaneProperty()->SetColor(1,0,0);//设置切片边框为红色(选择状态)

//上面的属性使用默认值即可

m_ImagePlaneWidget->SetResliceInterpolateToLinear();

m_ImagePlaneWidget->RestrictPlaneToVolumeOn();

m_ImagePlaneWidget->DisplayTextOn();

m_ImagePlaneWidget->GetTextProperty()->SetColor(1,0,0);//设置文本显示颜色为红色

m_ImagePlaneWidget->SetTextureVisibility(0);//关闭纹理映射,只显示切片边框,如果没有设置体数据,请调用SetTextureVisibility(int)函数关闭纹理映射。

实际使用的出现的问题:

内存释放问题:

在给切片设置体数据后(建立了体数据与vtkImagePlaneWidget连接),再删除体数据和vtkImagePlaneWidget对象时候,发现读入的体数据无法得到释放,

解决办法:

删除tkImagePlaneWidget对象之前,先断开与体数据之间的连接,

[cpp] view plain copy

1. <pre name="code" class="cpp">m_ImagePlaneWidget->SetInputData(nullptr);  

2. m_ImagePlaneWidget->SetInputConnection(nullptr);  

总结:VTKWidget交互部件使用注意事项:

要使用该部件,必须先调用 SetInteractor()函数设置交互器。作为交互部件,基类为vtkInteractorObserver,其工作在当前交互器风格下,即Widget通过交互器监听用户事件(也就是说,交互部件会比其他交互观察者优先地从交互器中截取自己所能响应的VTK事件并做出处理,对于不能响应的事件,该事件会继续由其他注册了的交互观察者vtkInteractorObserver的子类如vtkInteractorStyle响应处理)。

 ERROR: In ..\..\vtk-5.8.0\Widgets\vtkPlaneWidget.cxx, line 239
vtkPlaneWidget (0B73E550): The interactor must be set prior to enabling/disabling widget

上面说Widget中的交互器必须在启用/禁用widget之前事先被设置

②可以通过SetCurrentRenderer()设置渲染器,默认情况下渲染器都会从你所设置的交互器中获取,即设置交互器后可不用设置渲染器,Widget设置的交互器在哪里显示就在哪里显示。在定义可视化管线时,不需要定义相关的vtkActor,因为Widget内部会自动生成相关vtkActor,只需为Widget对象设置相应的vtkRenderer即可,Widget内部自动生成的vtkActor与为Widget对象设置的vtkRenderer形成完整的渲染管线,在vtkRenderer所在的渲染窗口的视图中显示渲染结果。

最后必须**Widget,使其能在渲染场景中显示。方法如下:

vtkInteractorObserver::SetEnabled(int);

vtkInteractorObserver::EnableOn();

vtkInteractorObserver::EnableOff();

vtkInteractorObserver::On();

vtkInteractorObserver::Off();

 

ERROR: In D:\VTK\VTK8.0.0-src\VTK-8.0.0\Rendering\Core\vtkTextActor.cxx, line 113

ERROR: In D:\VTK\VTK8.0.0-src\VTK-8.0.0\Rendering\Core\vtkTextActor.cxx, line 113

vtkTextActor (12B07840): Failed getting the TextRenderer instance!

 Qt VTK软件开发问题学习记录

解决方法:

在头文件中加入

#include "vtkAutoInit.h"

VTK_MODULE_INIT(vtkRenderingFreeType)

 

21. 子类指针不能隐式转换为父类指针?能,智能指针也可

编译一程序,出现如下错误:

..\..\DentalImplant\ImportModule\CTImportControl.cpp(53): error C2664:void vtkRenderer::AddVolume(vtkProp *):无法将参数 1从“vtkSmartPointer<vtkCornerAnnotation>”转换为“vtkProp *

..\..\DentalImplant\ImportModule\CTImportControl.cpp(53): note: 没有可用于执行该转换的用户定义的转换运算符,或者无法调用该运算符

vtkCornerAnnotation是vtkProp的子类,为何会有上述错误?

原来是没有#include "vtkCornerAnnotation.h"(子类的头文件)”。因为没有这个头文件,编译器根本不知道这两个类之间有继承关系。

Qt VTK软件开发问题学习记录解开注释即可。