- Vtk
基于VTK的Qt应用程序开发
- VTK附带的程序示例中大多是基于控制台的,作为可视化开发工具包,VTK也可以与很多流行的GUI开发工具整合,比如MFC、Qt、FLTK
- VTK与Qt整合的详细步骤:
- VTK工程的管理是用CMake的,而Qt自身有qmake工具,单纯的Qt程序用qmake来构建工程,确实很方便,但如果随着工程复杂度的增加以及工程依赖其他的函数库时,使用CMake来管理工程或许是一个明智的选择.单纯的Qt工程,怎么来写CMakeLists.txt脚本文件。
- # 程序所有源文件。# 定义变量Project_SRCS,其值为所列的文件列表 SET( Project_SRCS main.cpp )
- # 程序所有UI文件。 # 定义变量Project_UIS,其值为所列的文件列表 SET( Project_UIS YourQtWindows.ui )
- # 所有包含Q_OBJECT的头文件。 # 定义变量Project_MOC_HDRS,其值为所列的文件列表 SET( Project_MOC_HDRS YourQtProjectFiles.h )
- # 通过Qt的uic.exe生成UI文件对应的ui_XXXX.h文件 # 将生成的ui_XXXX.h文件放在变量Project_UIS_H里, # QT4_WRAP_UI就是干这个事情。 QT4_WRAP_UI( Project_UIS_H ${Project_UIS} )
- # 通过Qt的moc.exe生成包含Q_OBJECT的头文件对应的# moc_XXXX.cxx文件,将生成的moc_XXXX.cxx文件放在# 变量Project_MOC_SRCS里。QT4_WRAP_CPP就是干这个事情。QT4_WRAP_CPP( Project_MOC_SRCS ${Project_MOC_HDRS} )
6)# Qt的MOC和UIC程序生成的moc_XXXX.cxx和ui_XXXX.h
# 等文件是存放在CMake的“Where to build the binaries"
# 里指定的目录里,所以必须都这些路径包含进来。
INCLUDE_DIRECTORIES( ${Project_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
)
7)# Qt程序如果有资源文件(*.qrc),要包含资源文件,
# 然后用Qt的rcc.exe生成相应的qrc_XXXX.cpp文件。
# QT4_ADD_RESOURCES就是干这个事情。
SET( Project_RCCS YourProject.qrc)
QT4_ADD_RESOURCES( Project_RCC_SRCS ${Project_RCCS})
8)# 根据程序的cpp文件、头文件以及中间生成的ui_XXXX.h、
# moc_XXXX.cxx、qrc_XXXX.cxx等生成可执行文件,并链接
# Qt的动态库(Qt的动态库都定义在QT_LIBRARIES变量里了)
ADD_EXECUTABLE( YourProjectName
${Project_SRCS}
${Project_UIS_H}
${Project_MOC_SRCS}
${Project_RCC_SRCS}
)
TARGET_LINK_LIBRARIES ( YourProjectName ${QT_LIBRARIES} )
- 用CMake来管理Qt与VTK工程:在上面的基础上添加VTK相关的CMake脚本文件
- CMake脚本里增加工程环境变量的加载:缺少“vtkCommon.dll”文件
方法一:将缺少的dll文件全部拷贝的工程的Debug或者Release目录下(根据编译的版本)
方法二:将缺少的dll文件全部拷贝到Windows系统的目录下,即C:\Windows\system32或者C:\Windows\system目录下 但它同样有一个问题,假如你电脑里的VTK升级成别的版本,重新编译了一份动态库,或者是同时在你电脑里编译了好几个版本的VTK,这个时候就有点凌乱了。
原来动态编译的程序在启动的时候,会搜索程序所在的目录以及系统环境变量PATH所列的目录,如果这些目录有该程序需要的动态库时,就加载它们,如果没有,就提示无法加载相应动态库的错误。
可以在工程的CMakeLists.txt文件里添加一些脚本,把系统的PATH环境变量作一些更改,在工程启动之前加载这些环境变量。也就是(在工程的CMakeLists.txt最后添加):
#-----------------------------------------------------------------------------------
# Construct a list of paths containing runtime directories for project applications on Windows
set(PROJECT_RUNTIME_PATH "${VTK_LIBRARY_DIRS}/@VS_BUILD_TYPE@;
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/@VS_BUILD_TYPE@"
)
if(QT4_FOUND)
set(PROJECT_RUNTIME_PATH "${PROJECT_RUNTIME_PATH};${QT_LIBRARY_DIR}/../bin")
endif()
include(CreateWindowsBatchScript.cmake)
# If we are under Windows, create two batch files which correctly
# set up the environment for the application and for Visual Studio
if(WIN32)
set(VS_SOLUTION_FILE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.sln")
foreach(VS_BUILD_TYPE debug release)
CreateWindowsBatchScript("${CMAKE_SOURCE_DIR}/StartVS.bat.in"
${PROJECT_BINARY_DIR}/StartVS_${VS_BUILD_TYPE}.bat
${VS_BUILD_TYPE})
endforeach()
endif(WIN32)
提到了两个文件:CreateWindowsBatchScript.cmake以及StartVS.bat.in
CreateWindowsBatchScript.cmake:
function(CreateWindowsBatchScript in out build_type)
if(VTK_DIR)
set(VTK_BIN_DIR "${VTK_DIR}/bin/${build_type}")
else()
set(VTK_BIN_DIR)
endif()
set(VS_BUILD_TYPE ${build_type})
configure_file(${in} ${out} @ONLY)
# substitute again
configure_file(${out} ${out} @ONLY)
endfunction()
StartVS.bat.in:
@set CL=/D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
@set LINK=/LARGEADDRESSAWARE
PATH=@PROJECT_RUNTIME_PATH@;%PATH%
"@VS_SOLUTION_FILE@"
两个文件与工程的CMakeLists.txt放在同一级目录里。即类似下图的目录结构:
将工程通过CMake的configure->generate以后,即可生成StartVS_debug.bat和StartVS_release.bat两个脚本文件。如果你要编译、运行Debug版本的工程,即双击StartVS_debug.bat文件打开对应的工程,同理,Release版本的也一样。一旦按这种方式打开相应的工程,就不用再担心类似“无法加载***.dll文件”的错误了。如果你的程序还增加了ITK等函数库,也可以照着上面的脚本作相应的修改。
(4)用QVTKWidget整合Qt&VTK
VTK提供的类QVTKWidget 可以把它当作普通的Qt里的Widget来使用,甚至可以在Qt Designer里像Qt的其他标准控件一样拖来拖去
- 要实现QVTKWidget在Qt Designer里像Qt的其他标准控件一样拖来拖去,需要把编译生成的QVTKWidgetPlugin.dll/QVTKWidgetPlugin.lib(Release版本)复制到Qt的安装目录里的plugins\designer目录下
读入一幅图像,并在Qt界面上显示
槽在Qt的C++类中是private slots,是一种函数类型
槽是普通的 C++ 成员函数,可以被正常调用,它们唯一的特殊性就是很多信号可以与其相关联。当与其关联的信号(qt信号)被发射时,这个槽就会被调用。槽可以有参数,但槽的参数不能有缺省值。
既然槽是普通的成员函数,因此与其它的函数一样,它们也有存取权限。槽的存取权限决定了谁能够与其相关联。同普通的 C++ 成员函数一样,槽函数也分为三种类型,即 public slots、private slots 和 protected slots。
3)2.3 用vtkEventQtSlotConnect实现VTK事件与Qt槽的连接
类vtkEventQtSlotConnect可以实现VTK的事件与Qt的槽函数的连接,VTK的事件主要在vtkCommand.h文件里定义,包括鼠标单击、鼠标双击、鼠标移动等
m_Connections = vtkEventQtSlotConnect::New();
m_Connections->Connect(m_QVTKWidget->GetRenderWindow()->GetInteractor(),
vtkCommand::MouseMoveEvent,
this,
SLOT(updateCoords(vtkObject*)));
示例代码:VTK应用示例之VTK与Qt整合的示例
0)修改CMakeLists.txt cmake最小版本3.13.5 Qt4改成find_package(Qt5Widgets REQUIRED) QT4_WRAP_UI等的QT4改成 QT5
报错 include called with wrong number of arguments include 改成include_directories
- cmake下 source code选择工程文件所在文件夹 build 写文件夹下的bin(自己新建)
运行CMake –> Configure
- VTK_DIR这个选项就是指向编译的VTK目录,即E:/VTKx641/vtk-prefix/lib/cmake/vtk-8.1,准确地说,这个路径就是VTKConfig.cmake文件所在的完整路径(会自动识别)
CMAKE_INSTALL_PREFIX 工程文件夹下的prefix(自己新建)
- 再次“Configure”,直到没有红色的选项出现,最后“Generate
- 在工程文件下的bin找到“工程名.sln”文件打开
- 设置工程为启动项 f7编译 f5运行
报错
QVTKWidget 无法打开输入文件QVTK.lib 通用:添加依赖库文件。(选中项目-视图-属性页)链接器→输入→附加依赖项(lib)Ps.这里需要自己去文件夹下复制名字,每个版本都不一样,不要复制网上的。
可以使用doc命令dir /b,获取所有的lib文件名(/b是指不输出信息),然后复制粘贴到依赖库。我的是E:\vtk641\vtk-prefix\lib 或复制之前的附加依赖项
SetInput不是vtkImageViewer2的成员 someFilter - > SetInputConnection ( someReader - > GetOutputPort ());(版本)
setCodecForTr不是QTextCodec的成员 QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
改成
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));(版本)
纯vtk 加初始化
未定义标识符 .Cpp include”ui_*.h”
功能测试宏的参数必须是简单标识符
点击下图红色剪头按钮,弹出如下选项:
选择“仅生成”,然后清理,重新生成即可。
“生成+IntelliSense”是说:Visual Studio的IntelliSense功能类似其他IDE中的auto-completion,也就是能够自动补全。对于我来说只要调试就可以,所以关闭,就解决了。