旅游网站设计策划书,资源网站不好找了,网站免备案,linux网站备份VTK与Qt整合的示例
VTK附带的程序示例中大多是基于控制台的#xff0c;作为可视化开发工具包#xff0c;VTK也可以与很多流行的GUI开发工具整合#xff0c;比如MFC、Qt(题外话#xff1a;Qt已经被Digia从诺基亚手中收购了#xff0c;Qt现在的链接是#xff1a;http://qt… VTK与Qt整合的示例
VTK附带的程序示例中大多是基于控制台的作为可视化开发工具包VTK也可以与很多流行的GUI开发工具整合比如MFC、Qt(题外话Qt已经被Digia从诺基亚手中收购了Qt现在的链接是http://qt-project.org/也有已经编译好的版本http://code.google.com/p/qt-msvc-installer/downloads/list直接下载安装。可能因为大学课程里会教授MFC的内容一些非计算机专业的会偏向于采用MFC个人觉得对于非计算机专业而言如果一定要选择一种GUI工具做开发的话建议用Qt容易上手学习周期短)、FLTK(http://www.fltk.org/FLTK也是跨平台的是一种比较轻便的GUI工具VTK官方发布版本没有提供对FLTK的接口但可以借助类vtkFlRenderWindowInteractor来实现VTK与FLTK的整合)等等VTK的源码目录里(VTK-5.10\Examples\GUI)包含有VTK与Qt、MFC、Tcl等工具的整合。考虑到VTK对Qt的特殊照顾(VTK提供了很多针对Qt的类可以非常方便地与Qt整合)以及Qt自身的一些性质(如易用性、跨平台等)我们参考了VTK自带的一些例子给出了VTK与Qt整合的详细步骤。
1. CMakeLists.txt文件
我们已经知道了VTK工程的管理是用CMake的而Qt自身有qmake工具如果对于一些小工程而言单纯的Qt程序用qmake来构建工程确实很方便但如果随着工程复杂度的增加以及工程依赖其他的函数库时使用CMake来管理工程或许是一个明智的选择。而且随着你对CMake语法的了解你会发现用CMake来管理工程是一件非常棒的事情。
我们先看看对于单纯的Qt工程怎么来写CMakeLists.txt脚本文件。
1.1 用CMake来管理Qt工程
官方对于这个话题给出的解释在这里。我们引用一下这篇博文的图然后给出每句CMakeLists.txt脚本的注释结合这个图以及脚本的注释相信你应该能明白了。 #---------------------------------------------- # 下面这两行没什么好解释的 cmake_minimum_required( VERSION 2.8 ) project( YourProjectName ) #---------------------------------------------- # 下面这两行也没什么好解释的 find_package( Qt4 REQUIRED ) include( ${QT_USE_FILE} ) #---------------------------------------------- # 程序所有源文件。TODO:在此处添加源文件 # 定义变量Project_SRCS其值为所列的文件列表 SET( Project_SRCS main.cpp ) #---------------------------------------------- # 程序所有UI文件。TODO:在此处添加UI文件 # 定义变量Project_UIS其值为所列的文件列表 SET( Project_UIS YourQtWindows.ui ) #---------------------------------------------- # 所有包含Q_OBJECT的头文件。TODO:在此处添加头文件 # 定义变量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} ) #----------------------------------------------- # Qt的MOC和UIC程序生成的moc_XXXX.cxx和ui_XXXX.h # 等文件是存放在CMake的“Where to build the binaries # 里指定的目录里所以必须都这些路径包含进来。 INCLUDE_DIRECTORIES( ${Project_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) #----------------------------------------------- # Qt程序如果有资源文件(*.qrc)要包含资源文件 # 然后用Qt的rcc.exe生成相应的qrc_XXXX.cpp文件。 # QT4_ADD_RESOURCES就是干这个事情。 SET( Project_RCCS YourProject.qrc) QT4_ADD_RESOURCES( Project_RCC_SRCS ${Project_RCCS}) #----------------------------------------------- # 根据程序的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} )
1.2 用CMake来管理Qt与VTK工程
我们在上面的基础上添加VTK相关的CMake脚本文件如下 #---------------------------------------------------------------------------------- cmake_minimum_required( VERSION 2.8 ) project( CombineQtAndVTK ) #---------------------------------------------------------------------------------- find_package( VTK REQUIRED ) find_package( Qt4 REQUIRED ) include( ${VTK_USE_FILE} ) include( ${QT_USE_FILE} ) #---------------------------------------------------------------------------------- SET( PROJECT_SRCS main.cpp ProjectMainWindow.cpp ) SET( PROJECT_UIS ProjectMainWindow.ui ) SET( PROJECT_MOC_HDRS ProjectMainWindow.h ) #---------------------------------------------------------------------------------- QT4_WRAP_UI( PROJECT_UIS_H ${PROJECT_UIS} ) QT4_WRAP_CPP( PROJECT_MOC_SRCS ${PROJECT_MOC_HDRS} ) #---------------------------------------------------------------------------------- INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${VTK_DIR} ) ADD_EXECUTABLE( CombineQtAndVTK ${PROJECT_SRCS} ${PROJECT_UIS_H} ${PROJECT_MOC_SRCS} ) TARGET_LINK_LIBRARIES ( CombineQtAndVTK ${VTK_LIBRARIES} QVTK )
以上的脚本除了红色字体标注的跟1.1注释的不太像之外其他的都一样不再解释。
1.3 CMake脚本里增加工程环境变量的加载
很多非计算机专业的用户在使用VTK进行编程时经常会碰到类似下图所示的一些错误。 碰到这样的错误以后可能很多用户就不知道怎么处理了其实上面的提示信息已经写得非常清楚了就是缺少“vtkCommon.dll”文件。但是又有人会说我的电脑里明明有这个文件存在啊为什么会找不到呢
一般的解决方法可能是
方法一将缺少的dll文件全部拷贝的工程的Debug或者Release目录下(拷贝的时候要注意你编译的VTK是Debug版本的还是Release版本的如果拷错的话又会出现其他不可预知的错误了)。但是这个方法是你每建一个工程运行工程之前得把缺少的动态库文件又要拷贝过去如果你不嫌麻烦的话可以采用。
方法二将缺少的dll文件全部拷贝到Windows系统的目录下即C:\Windows\system32或者C:\Windows\system目录下这个方法是你拷贝一次以后再基于你拷贝的VTK动态库的工程运行的时候问题都解决了。但它同样有一个问题假如你电脑里的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 PATHPROJECT_RUNTIME_PATH;%PATH% VS_SOLUTION_FILE 将工程通过CMake的configure-generate以后即可生成StartVS_debug.bat和StartVS_release.bat两个脚本文件。如果你要编译、运行Debug版本的工程即双击StartVS_debug.bat文件打开对应的工程同理Release版本的也一样。一旦按这种方式打开相应的工程就不用再担心类似“无法加载***.dll文件”的错误了。如果你的程序还增加了ITK等函数库也可以照着上面的脚本作相应的修改。
注意使用时将CreateWindowsBatchScript.cmake和StartVS.bat.in两个文件与工程的CMakeLists.txt放在同一级目录里。即类似下图的目录结构 2. 用QVTKWidget整合QtVTK
Qt与VTK的整合可以使用VTK提供的类QVTKWidget看这个类名就知道这个类其实就是一个Qt里的Widget (QVTKWidget派生自QWidget)所以可以把它当作普通的Qt里的Widget来使用甚至可以在Qt Designer里像Qt的其他标准控件一样拖来拖去。
2.1 在Qt Designer里集成
要实现QVTKWidget在Qt Designer里像Qt的其他标准控件一样拖来拖去需要把编译生成的QVTKWidgetPlugin.dll/QVTKWidgetPlugin.lib(Release版本)复制到Qt的安装目录里的plugins\designer目录下。完了以后你会在Qt Designer里面看到如下的控件 2.2 读入一幅图像并在Qt界面上显示
接下来我们来完成一个小功能就是读入一幅JPG图像然后在Qt界面上用VTK来显示。功能非常简单程序也非常简单。上代码
ProjectMainWindow.h: #ifndef Project_MainWindow_H #define Project_MainWindow_H #include QMainWindow #include ui_ProjectMainWindow.h #include vtkSmartPointer.h class vtkImageViewer2; class vtkRenderer; class ProjectMainWindow : public QMainWindow, public Ui::ProjectMainWindow { Q_OBJECT public: ProjectMainWindow(); ~ProjectMainWindow(); private slots: //响应打开图像文件的槽函数 void onOpenSlot(); private: vtkSmartPointer vtkImageViewer2 m_pImageViewer; vtkSmartPointer vtkRenderer m_pRenderder; }; #endif ProjectMainWindow.cpp: #include ProjectMainWindow.h #include QFileDialog #include QDir #include vtkRenderWindow.h #include vtkRenderer.h #include vtkImageViewer2.h #include QVTKWidget.h #include vtkJPEGReader.h #include vtkImageActor.h ProjectMainWindow::ProjectMainWindow() { setupUi(this); m_pImageViewer vtkSmartPointer vtkImageViewer2 ::New(); m_pRenderder vtkSmartPointer vtkRenderer ::New(); // 设置m_QVTKWidget的渲染器 m_QVTKWidget-GetRenderWindow()-AddRenderer(m_pRenderder); //连接打开的信号与相应的槽 connect( m_OpenAction, SIGNAL( triggered() ), this, SLOT( onOpenSlot() ) ); } ProjectMainWindow::~ProjectMainWindow() { } void ProjectMainWindow::onOpenSlot() { QString filter; filter JPEG p_w_picpath file (*.jpg *.jpeg); QDir dir; QString fileName QFileDialog::getOpenFileName( this, QString(tr(打开图像)), dir.absolutePath() , filter ); if ( fileName.isEmpty() true ) return; // 支持带中文路径的读取 QByteArray ba fileName.toLocal8Bit(); const char *fileName_str ba.data(); // 用vtkJPEGReader读取JPG图像 vtkSmartPointervtkJPEGReader reader vtkSmartPointervtkJPEGReader::New(); reader-SetFileName(fileName_str); // 将reader的输出作为m_pImageViewer的输入并设置m_pImageViewer与渲染器m_pRenderer的关联 m_pImageViewer-SetInput(reader-GetOutput()); m_pImageViewer-UpdateDisplayExtent(); m_pImageViewer-SetRenderWindow(m_QVTKWidget-GetRenderWindow()); m_pImageViewer-SetRenderer(m_pRenderder); m_pImageViewer-SetupInteractor(m_QVTKWidget-GetRenderWindow()-GetInteractor()); m_pImageViewer-SetSliceOrientationToXY(); //默认就是这个方向的 m_pImageViewer-GetImageActor()-InterpolateOff(); m_pRenderder-ResetCamera(); m_pRenderder-DrawOn(); m_QVTKWidget-GetRenderWindow()-Render(); } 程序运行结果 2.3 用vtkEventQtSlotConnect实现VTK事件与Qt槽的连接
类vtkEventQtSlotConnect可以实现VTK的事件与Qt的槽函数的连接VTK的事件主要在vtkCommand.h文件里定义包括鼠标单击、鼠标双击、鼠标移动等等如
vtkCommand::ProgressEvent
vtkCommand::ErrorEvent
vtkCommand::WarningEvent
vtkCommand::PickEvent
vtkCommand::StartPickEvent
vtkCommand::EndPickEvent
vtkCommand::CharEvent
vtkCommand::KeyPressEvent
vtkCommand::KeyReleaseEvent
vtkCommand::LeftButtonPressEvent
vtkCommand::LeftButtonReleaseEvent
vtkCommand::MouseMoveEvent
……
具体的代码实现 private slots: //响应鼠标移动的消息实时输出鼠标的当前位置 void updateCoords(vtkObject* obj); private: vtkEventQtSlotConnect* m_Connections;
源文件 //构造函数里 m_Connections vtkEventQtSlotConnect::New(); m_Connections-Connect(m_QVTKWidget-GetRenderWindow()-GetInteractor(), vtkCommand::MouseMoveEvent, this, SLOT(updateCoords(vtkObject*))); //槽函数的实现 void ProjectMainWindow::updateCoords(vtkObject* obj) { // 获取交互器 vtkRenderWindowInteractor* iren vtkRenderWindowInteractor::SafeDownCast(obj); // 获取鼠标的当前位置 int event_pos[2]; iren-GetEventPosition(event_pos); QString str; str.sprintf(x%d : y%d, event_pos[0], event_pos[1]); m_StatusBar-showMessage(str); }
程序运行结果 示例代码及该博文文档下载地址http://download.csdn.net/detail/www_doling_net/5137375 本文来源 http://blog.csdn.net/www_doling_net/article/details/8668870
转载于:https://blog.51cto.com/2845385/1157522