生活随笔
收集整理的這篇文章主要介紹了
基于VTK的Qt应用程序开发
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
分類: VTK應用示例 2013-03-13 15:51 6622人閱讀 收藏 舉報
VTKQtCMake
目錄(?)[+]
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腳本的注釋,結合這個圖以及腳本的注釋,相信你應該能明白了。
?
[plain] view plaincopy
#----------------------------------------------??#?下面這兩行,沒什么好解釋的??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腳本文件,如下:
[plain] view plaincopy
#----------------------------------------------------------------------------------??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最后添加):
[plain] view plaincopy
#-----------------------------------------------------------------------------------??#?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:
?
[plain] view plaincopy
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:
?
[plain] view plaincopy
@set?CL=/D_CRT_SECURE_NO_DEPRECATE?/D_CRT_NONSTDC_NO_DEPRECATE??@set?LINK=/LARGEADDRESSAWARE?????PATH=@PROJECT_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整合Qt&VTK
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:
[cpp] view plaincopy
#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:
[cpp] view plaincopy
#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->GetRenderWindow()->AddRenderer(m_pRenderder);?????????????????????connect(?m_OpenAction,?SIGNAL(?triggered()?),?this,?SLOT(?onOpenSlot()?)?);??}?????ProjectMainWindow::~ProjectMainWindow()??{??}?????void?ProjectMainWindow::onOpenSlot()??{?????????QString?filter;?????????filter?=?"JPEG?image?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();?????????????????????vtkSmartPointer<vtkJPEGReader>?reader?=?vtkSmartPointer<vtkJPEGReader>::New();?????????reader->SetFileName(fileName_str);?????????????????????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
……
具體的代碼實現:
[cpp] view plaincopy
private?slots:??????????????????void?updateCoords(vtkObject*?obj);?????private:?????????vtkEventQtSlotConnect*?m_Connections;??
源文件:
[cpp] view plaincopy
?????????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/8763686
================================================
總結
以上是生活随笔為你收集整理的基于VTK的Qt应用程序开发的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。