主要參考:http://m.blog.csdn.net/blog/u011017966/40984473
1. visual studio 2010 的安裝
安裝路徑選擇D:\Program Files (x86)\Microsoft Visual Studio 10.0,
2. QT的安裝
安裝路徑選擇:D:\Qt
安裝結束后添加系統路徑:


3. 安裝qt-vs-addin-1.2.3-opensource
安裝路徑為:D:\Program Files (x86)\Digia\Qt5VSAddin
安裝完成后就可以在vs2010中看到QT的菜單項了,

4. Qt與VS2010的整合
這時還不能打開QT的Open QT Project File,需要向VS中添加qt的make路徑,如下所示:
QT->QT Options->Add

至此,QT與vs2010完成整合。
注意此方法是在VS2010環境下使用QT,QT Creater環境下的使用還需要調節,方法沒有找到合適的,主要估計是因為一些環境變量的設置不對,比較煩。
上面的主要參考資料主要來源於,在此表示感謝:
http://blog.sina.com.cn/s/blog_a6fb6cc90101gynd.html
5. VTK的編譯
- 解壓下載的vtk源文件於文件夾D:\VTK\VTK-6.1.0下,新建文件夾D:\VTK\VTKBuild用於放置編譯文件,在解壓源文件的同時解壓下載的數據文件vtkdata,解壓路徑選擇在D:\VTK\VTK-6.1.0下,會自動解壓到D:\VTK\VTK-6.1.0下的.ExternalData文件夾內。
- 打開cmake,source code選擇D:\VTK\VTK-6.1.0,build the binaries 選擇D:\VTK\VTKBuild,點confige ,編譯器選擇visual studio 10,此為32位版本,確認,生成下述畫面

在上述畫面中點擊Advanced,選擇以下:(下面的選項在常規選項中可以選擇,不用點擊Advance)
a.BUILD_SHARED_LIBIRARES勾選,此為是否編譯動態鏈接庫,選擇編譯。
b.BUILD_EXAMPLES:此為編譯例子,可以選擇編譯或者不編譯,若編譯,會在編譯生成的bin文件夾下生成例子的 exe可執行文件,方便理解源碼的例子是什么運行結果,我選擇了不編譯。
c.點擊上述add Entry,添加路徑:qt的安裝路徑,如下所示:

d.VTK_GROUP_QT,因為選擇用QT,所以勾選此項。
- 再次點擊confige,出現錯誤,點擊Advanced,在下方找到VTK_QT_VESION,改成5,確認QT_QMAKE_EXECUTABLE為你的qmake.exe地址,再次confige,沒有錯誤沒有紅色選項后點擊generate,生成visual studio 平台的項目文件。
- 在D:\VTK\VTKBuild文件夾下找到VTK.sln文件,以管理員方式打開,或者先以管理員方式打開visual studio再在里面找到vtk.sln文件打開,准備兩次編譯
a.relase版本編譯:如下,選擇relase版本,點擊菜單欄build->build solution,等待。

b.等待release版本完成后,點擊debug版本進行編譯,等待。
- 待編譯完成后,選擇D:\VTK\VTKBuild\路徑下的release版本中的QVTKWidgetPlugin.lib,QVTKWidgetPlugin.dll,拷貝到文件夾D:\Qt\Qt5.3.2\5.3\msvc2010_opengl\plugins\designer下,就可以在QT design中看到VTKWidgts選項,如下
- Vtk的安裝
上面的步驟只是將下載下來的VTK源碼在windows的平台上生成了相當於setup文件,就是install工程,還需要在編譯 install工程才能在cmake時候的變量CMAKE_INSTALL_PREFIX下生成安裝文件,(在前面編譯的時候INSTALL工程都是skip的,沒有編譯),在visual studio 中的solution中找打INSTALL中,點擊BUILD ONLY PROJECT,build安裝,如下圖

編譯沒有錯誤的話會在C:\Program Files (x86)\VTK文件(如果cmake時沒有更改CMAKE_INSTALL_PREFIX)下生成如下文件:

表示vtk安裝成功。(注:INSTALL工程只能在管理員權限內才能成功編譯安裝,因此必須以管理員權限打開visual studio進行編譯)
- 添加路徑:如2步所示打開系統環境變量,添加:
a.PATH=C:\Program Files(x86)\VTK\bin; 如下圖:

b.QTDIR=D:\Qt\Qt5.3.2\5.3\msvc2010_opengl,如下圖:

圖11
- VTK編譯安裝的步驟的參考方法來自於官方:
a.http://www.vtk.org/Wiki/VTK/Configure_and_Build#Qt5..2A,截圖:

b.http://www.vtk.org/Wiki/VTK/Tutorials/QtSetup#Windows,截圖

本篇博文的主要想說的內容是兩個部分,一部分是如何用cmake來講vtk和qt結合起來構建vs2010內的工程的具體方法(學會這個以后如果以后還想在這個里面添加itk就可以直接類比vtk的方法,會簡單很多),另一部分主要介紹cmakelists.txt的寫法。然后博文的組織上是分為單獨vtk的測試vtk+qt的測試兩部分。
1、cmake管理vtk工程
1.1新建工程
在自己工作的目錄下新建文件夾Cylinder,該文件夾下新建一個cpp文件Cylinder.cpp,該文件為工程源文件,一個CMakeLists.txt文件,該文件為該工程的cmake配置文件。
打開Cylinder.cpp,拷貝下述代碼進去保存:
//
// This simple example shows how to do basic rendering and pipeline
// creation using C++.
//
#include "vtkCylinderSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkProperty.h"
#include "vtkCamera.h"
int main()
{
// This creates a polygonal cylinder model with eight circumferential facets.
//
vtkCylinderSource *cylinder = vtkCylinderSource::New();
cylinder->SetResolution(8);
// The mapper is responsible for pushing the geometry into the graphics
// library. It may also do color mapping, if scalars or other attributes
// are defined.
//
vtkPolyDataMapper *cylinderMapper = vtkPolyDataMapper::New();
cylinderMapper->SetInputConnection(cylinder->GetOutputPort());
// The actor is a grouping mechanism: besides the geometry (mapper), it
// also has a property, transformation matrix, and/or texture map.
// Here we set its color and rotate it -22.5 degrees.
vtkActor *cylinderActor = vtkActor::New();
cylinderActor->SetMapper(cylinderMapper);
cylinderActor->GetProperty()->SetColor(1.0000, 0.3882, 0.2784);
cylinderActor->RotateX(30.0);
cylinderActor->RotateY(-45.0);
// Create the graphics structure. The renderer renders into the
// render window. The render window interactor captures mouse events
// and will perform appropriate camera or actor manipulation
// depending on the nature of the events.
//
vtkRenderer *ren1 = vtkRenderer::New();
vtkRenderWindow *renWin = vtkRenderWindow::New();
renWin->AddRenderer(ren1);
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(renWin);
// Add the actors to the renderer, set the background and size
//
ren1->AddActor(cylinderActor);
ren1->SetBackground(0.1, 0.2, 0.4);
renWin->SetSize(200, 200);
// We'll zoom in a little by accessing the camera and invoking a "Zoom"
// method on it.
ren1->ResetCamera();
ren1->GetActiveCamera()->Zoom(1.5);
renWin->Render();
// This starts the event loop and as a side effect causes an initial render.
iren->Start();
// Exiting from here, we have to delete all the instances that
// have been created.
cylinder->Delete();
cylinderMapper->Delete();
cylinderActor->Delete();
ren1->Delete();
renWin->Delete();
iren->Delete();
return 0;
}
打開cmakelists.txt,拷貝下述代碼進去保存:
cmake_minimum_required(VERSION 2.8.5 FATAL_ERROR)
project(Cylinder)
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
add_executable(${PROJECT_NAME} Cylinder.cpp)
target_link_libraries(${PROJECT_NAME} ${VTK_LIBRARIES})
關於上面的代碼的講解,可以參考博文http://blog.csdn.net/www_doling_net/article/details/8532742中的介紹。
1.2 cmake配置生成工程文件

點擊confige配置,默認選擇visual studio 10(32編譯版本),配置完成后沒有錯誤如圖2選擇generate生成工程文件如圖3,在我的目錄的build文件夾下會生成如下圖4:

圖2

圖3

圖4
1.3編譯運行
打開cylinder.sln文件,鼠標右鍵選擇properties,然后選擇Linker內的input,在附加依賴項Additional Dependencies 中找到Qt5::Widgets.lib刪除,確定。這塊的原因是因為我們在編譯安裝VTK的時候選擇了使用QT5,所以每回新建的工程用cmake管理都會添加Qt5::Widgets.lib頭文件,但是在cmakeLists.txt文件中又沒有配置QT的選項,所以如果不刪除Qt5::Widgets.lib就會出現“LINK : fatal error LNK1104: cannot open file'Qt5::Widgets.lib'”的錯誤。操作如下圖5所示:
Cylinder右鍵--》Properties-》Linker-》Input-》Additional Dependencies-》Edit,找到Qt5::Widgets.lib刪除:

圖5
完成后,右擊cylinder工程,選擇SetUp As A StratUp Project,將Cylinder工程設為運行工程。否則編譯生成的文件找不到運行啟動項。
點擊build運行,運行結果如下圖6:
然后好多像我這樣的新手雖然看了很多也不是很了解到底Cmake這個工具在在這個過程中起到的是什么作用。我在這邊說一下我的理解,希望可以對大家有所幫助,有不對的地方也希望大家指出來。
首先我們都知道CMake是個跨平台的工程構建工具,這句話怎么理解呢,在我們安裝VTK的時候,我們如果點開看源碼,可以發現源碼的c++文件的后綴名都是.cxx,這個后綴名是Linux平台的c++源文件,我們常使用的windows系統的c++的源文件后綴名應該是cpp才對,也就是說vtk的源碼並不是針對windows平台開發的,那為什么我們可以編譯安裝呢?這就是cmake程序的作用。Cmake可以將VTK的源代碼根據我們的平台(例如vs2010)生成針對這個平台的工程文件,就相當於我們直接在vs2010中新建的工程文件是針對vs2010這個平台的,也就是說,我們下載的VTK的源代碼里面只有源代碼和CmakeLists.txt文件,它是不針對平台和編譯器的,當我們用cmake配置VTK的源碼選擇編譯器位為vs2010后並generate生成后,生成的build文件夾下的內容就是針對vs2010的32位編譯器的工程文件了,這個文件夾下面有源文件、有告訴編譯器需要連接哪些庫文件、需要根據什么順序編譯源文件的工程等的配置文件,而這些配置文件就是cmake針對vs2010生成的。
所以在這個示例中,我們如果用cmake管理我們新建的工程,在我們寫的CMakeList.txt內我們就已經寫明我們這個工程需要鏈接哪些頭文件庫文件等,generate生成的工程文件中就已經有需要添加哪些頭文件庫文件的配置文件了,所以這也是我們用cmake生成的工程不用手動添加頭文件庫文件而用vs2010新建的工程需要手動添加的原因。
在這個過程中我們一定要注意通過編譯源代碼生成二進制的可執行文件的過程是由編譯器完成的,跟CMake沒有關系,CMake做的只是告訴編譯器怎么編譯。
當然,如果我們在cmake進行configure時選擇Linux平台的Mingw編譯器,那生成的工程文件就是針對Linux平台的Mingw編譯器的,就實現了我們編寫的代碼的跨平台。
另外我想說一下后面的開發的步驟。
其實上面給出的CMakeList.txt代碼中,我們只需要將project(Cylinder)中的工程名改成我們以后自己的工程名,find_package(VTK REQUIRED),include(${VTK_USE_FILE})每次都不需要改動,add_executable(${PROJECT_NAME} Cylinder.cpp)是由源文件配置編譯選項生成目標代碼的語句,只需要將后面的源文件Cylinder.cpp改成我們自己的cpp文件即可,然后因為我們默認生成的目標代碼的名稱就為工程名,而${PROJECT_NAME}就是取工程文件名,所以也是不需要改動的。然后對於語句target_link_libraries(${PROJECT_NAME} ${VTK_LIBRARIES})是連接庫文件的語句,對於初學者並不知道該添加哪些庫文件的情況下最簡單的方法就是將編譯生成的VTK所有的庫文件全部添加,即${VTK_LIBRARIES},所以就會出現我們上面需要刪除Qt5::Widgets.lib的情況。這樣確實簡單,但是缺點也是顯而易見的就是編譯的工程中有很多沒用的庫文件,會拖慢編譯速度,增加工程文件體積,所以在弄清楚你用哪些庫文件后(這塊的內容還是可以參考上面那篇博文內容,里面有講解如何根據自己所使用的內確定需要的庫文件),只添加你需要的是明智的選擇的。
然后在我們需要新建一個工程時,我們只需要將我們的以前做的工程原封不動的復制過來,然后更改工程名、cpp文件的名字(當然如果你工程簡單可以直接將cpp命名為main.cpp以后也就不用改了,但這不是個好習慣),然后在CMakeList.txt中更改工程名和源文件名,就可以編譯工程了,最后在打開的工程中修改cpp文件,編寫新的代碼即可,這樣做的好處是可以用vs的自動代碼提示功能了。
這節的最后給大家推薦下http://www.vtk.org/Wiki/VTK/Examples/Cxx就是vtk官網上的例子,從這邊進去的例子都是帶有CMakeList.txt代碼的,大家學習cmake的關於VTK的寫法可以上這個網站去看。而且經常不知道怎么實現的功能上面都有例子,非常實用。
2、cmake管理vtk+qt工程
在講這邊的測試程序前,我們需要先了解QT的工程的編譯步驟和原理,這邊的過程請大家參考博文http://blog.csdn.net/www_doling_net/article/details/8668870的1.1節和1.2節,講的很清楚,特別是那張圖,引用出來粘貼在這里圖7:
要理解下面貼出來的CmakeLists代碼的內容大家一定要返回去看看這篇博文的內容,他講了QT新建工程的.ui(用QT Designer設計的界面文件),.qrc(資源文件),使用槽函數的頭文件(在頭文件中包含QObject)等如何通過qt的工具如qmake等轉變成vs編譯器可以識別的c++代碼的,這也是用cmake管理qt工程的基礎。
2.1建立vtk+qt工程
<span style="background-color: rgb(255, 255, 255);">project(testproject) # Find includes in corresponding build directories #這句必須加上,所以標記下這句我們需要復制到我們的工程</span> set(CMAKE_INCLUDE_CURRENT_DIR ON) # Instruct CMake to run moc automatically when needed. #這句是設置自動MOC為開,MOC就是我們用來將qt的ui文件,包含槽函數的頭文件等翻譯成c++文件的工具, #這個不好控制,所以我們還是按照東靈博客講的方法自己翻譯,所以這句不要 set(CMAKE_AUTOMOC ON) # Find the QtWidgets library #這句是找到QT5組建,因為測試程序中只用到Qt5Widgets這個組件,所以只添加這一個 #這句必須有,標記下等會添加</span> find_package(Qt5Widgets) # Tell CMake to create the helloworld executable #這個和前面VTK的一樣,沒什么說的 add_executable(helloworld WIN32 main.cpp) # Use the Widgets module from Qt 5. #最后一句是連接庫函數,這句話是使用新版的好處,這句話可以自動添加目錄、編譯定義、和標志符等, target_link_libraries(helloworld Qt5::Widgets) </span>而我們可以在老版的官方的寫法下面發現這樣的語句:
<span style="background-color: rgb(255, 255, 255);">include_directories(${Qt5Widgets_INCLUDE_DIRS})
add_definitions(${Qt5Widgets_DEFINITIONS})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")</span>
這句話而這些話就是新版的最后一句話的可以完成的工作,所以我們直接用新版的說法,所以結合東靈博客的寫法,VTK的寫法和我們這塊的討論,我們可以得到我們測試程序的CMakeLists.txt的寫法:<span style="background-color: rgb(255, 255, 255);">#因為我們使用的新版本,所以最低要求是2.8.11
cmake_minimum_required( VERSION 2.8.11 )
project( CombineQtAndVTK )
#這句話是我們剛才標記添加的內容
set(CMAKE_INCLUDE_CURRENT_DIR ON)
#這兩句是VTK的內容,沒什么說的
find_package( VTK REQUIRED )
include( ${VTK_USE_FILE} )
#這句話是剛才標價添加的
find_package(Qt5Widgets)
#這個include是根據東靈博客的內容
include_directories(${PROJECT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${VTK_DIR})
#這片的內容是設置MOC翻譯的內容,我們只需要將東靈博客的QT4改成QT5就可以
SET( PROJECT_SRCS
main.cpp
testqtwithvtk.cpp
testqtwithvtk.h
)
SET( PROJECT_UIS
testqtwithvtk.ui
)
SET( PROJECT_MOC_HDRS
testqtwithvtk.h
)
QT5_WRAP_UI( PROJECT_UIS_H
${PROJECT_UIS}
)
QT5_WRAP_CPP( PROJECT_MOC_SRCS
${PROJECT_MOC_HDRS}
)
#這句話就是添加可執行文件了
ADD_EXECUTABLE( CombineQtAndVTK
${PROJECT_SRCS}
${PROJECT_UIS_H}
${PROJECT_MOC_SRCS}
)
#這邊我們要包含的東西就是vtk和QT5各自需要包含的頭文件
TARGET_LINK_LIBRARIES ( CombineQtAndVTK
${VTK_LIBRARIES}
Qt5::Widgets
)</span>
至此,我們CMakeLists.txt就寫完了,雖然我們的源文件內基本沒有程序文件,但這並不影響cmake進行配置,如圖8所示:

圖8
2.2編寫源文件
打開cmake generate生成的CombineQtAndVTK.sln,打開工程,我們可以看到下面圖9所示的文檔結構:

圖9
需要說明的是:ui_testqtwithvtk.h是testqtwithvtk.ui生成的文件,所有在testqtwithvtk.ui中所做的更改都會重新生成ui_testqtwithvtk,注意ui_testqtwithvtk我們以后會經常打開研究。moc_testqtwithvtk.cpp是testqtwithvtk.h MOC后生成文件,這個我現在還覺得不需要看,所以不需要太關注。然后我們打開testqtwithvtk.ui,進行UI設計,我們拖一個QVTKWidgets進去,然后再拖一個Label進去,然后新建菜單項New Open Save,並更改對象名稱如下圖10所示:

圖10
然后點擊工程進行build,使testqtwithvtk.ui所做的更改可以保存到ui_testqtwithvtk.h文件中。然后打開testqtwithvtk.h,其內容為:
<span style="background-color: rgb(255, 255, 255);">#ifndef TESTQTWITHVTK_H
#define TESTQTWITHVTK_H
#include <QtWidgets/QMainWindow>
#include "ui_testqtwithvtk.h"
#include "vtkSmartPointer.h"
class vtkImageViewer2;
class vtkRenderer;
class vtkEventQtSlotConnect;
class TestQTWithVTK : public QMainWindow
{
Q_OBJECT
public:
TestQTWithVTK(QWidget *parent = 0);
~TestQTWithVTK();
private:
Ui::TestQTWithVTKClass ui;
private slots:
//響應打開圖像文件的槽函數
void onOpenSlot();
private:
vtkSmartPointer< vtkImageViewer2 > m_pImageViewer;
vtkSmartPointer< vtkRenderer > m_pRenderder;
private slots:
//響應鼠標移動的消息,實時輸出鼠標的當前位置
void updateCoords(vtkObject* obj);
private:
vtkEventQtSlotConnect* m_Connections;
};
#endif // TESTQTWITHVTK_H</span>
<span style="background-color: rgb(255, 255, 255);">#include "testqtwithvtk.h"
#include <QFileDialog>
#include <QDir>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkImageViewer2.h>
#include <QVTKWidget.h>
#include <vtkBMPReader.h>
#include <vtkImageActor.h>
#include "vtkEventQtSlotConnect.h"
#include "vtkCommand.h"
TestQTWithVTK::TestQTWithVTK(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
m_pImageViewer = vtkSmartPointer< vtkImageViewer2 >::New();
m_pRenderder = vtkSmartPointer< vtkRenderer >::New();
m_Connections = vtkEventQtSlotConnect::New();
// 設置m_QVTKWidget的渲染器
ui.qvtkWidget->GetRenderWindow()->AddRenderer(m_pRenderder);
//連接打開的信號與相應的槽
connect(ui.actionOpen, SIGNAL( triggered() ), this, SLOT( onOpenSlot() ) );
m_Connections->Connect(ui.qvtkWidget->GetRenderWindow()->GetInteractor(),
vtkCommand::MouseMoveEvent,
this,
SLOT(updateCoords(vtkObject*)));
}
TestQTWithVTK::~TestQTWithVTK()
{
m_Connections->Delete();
}
void TestQTWithVTK::onOpenSlot()
{
QString filter;
filter = "BMP image file (*.bmp)";
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圖像
vtkSmartPointer<vtkBMPReader> reader = vtkSmartPointer<vtkBMPReader>::New();
reader->SetFileName(fileName_str);
// 將reader的輸出作為m_pImageViewer的輸入,並設置m_pImageViewer與渲染器m_pRenderer的關聯
m_pImageViewer->SetInputConnection(reader->GetOutputPort());
//m_pImageViewer->UpdateDisplayExtent();
m_pImageViewer->SetRenderWindow(ui.qvtkWidget->GetRenderWindow());
m_pImageViewer->SetRenderer(m_pRenderder);
m_pImageViewer->SetupInteractor(ui.qvtkWidget->GetRenderWindow()->GetInteractor());
m_pImageViewer->SetSliceOrientationToXY(); //默認就是這個方向的
m_pImageViewer->GetImageActor()->InterpolateOff();
m_pRenderder->ResetCamera();
m_pRenderder->DrawOn();
ui.qvtkWidget->GetRenderWindow()->Render();
}
void TestQTWithVTK::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]);
ui.statusBar->showMessage(str);
}
</span>
main.cpp的程序內容一般不用更改。
2.3 編譯運行

