一、前言
今天實現的主要功能是通過vtk讀取jpg圖片(只能夠讀取.jpg文件),然后通過QT顯示出來,整個程序的框架是QT GUIApplication
版本:
VS | 2019 |
VTK | 8.2.0 |
QT | 5.13.1 |
版本配置 | VS 為release x64(這個是工程建立的時候設置的解決方案屬性) VTK也是使用relealse x64編譯獲得的(這個是VTK安裝的過程的編譯選項) QT也使用msvc2017-64bit(這個是QT安裝的時候在VS平台配置的,如果發現不對要更改) |
二、參考博客
三、工程建立
1、新建一個QGui Application
設置VS項目解決方案配置為release x64:
2、打開.ui文件
這個時候會出現一個QT designer界面,我們需要注意是否存在QVTKWidget控件
如果存在這個控件(如果沒有參見后面的解決辦法),那么我們把這個控件拖動到中間。
3、然后拖動一個pushButton,一個linText, 形成的界面和上一個例子大概是一樣的,最后的顯示功能也是一樣,只不過這個時候是采用的vtk顯示圖像。
4、保存ui文件,然后關閉
5、按照之前的博客講述的方法編譯ui文件,重新掃描解決方案
6、在屬性管理器Release x64下面添加屬性表:
把配置好的兩個屬性表復制到本工程目錄,然后點擊Release x64,然后右鍵,選擇添加現有屬性表
7、將代碼復制到文件中:
這里我的項目名字為:VTKReadJpg_InQT_Test
各個文件代碼如下:
VTKReadJpg_InQT_Test.h

#pragma once //#pragma warning(disable: 26498 ) /*QT file*/ #include <QtWidgets/QMainWindow> #include "ui_VTKReadJpg_InQT_Test.h" #include <QFileDialog> #include <QDir> #include <qstring.h> #include <qlineedit.h> #include <QpushButton> /*vtk File*/ #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkImageViewer2.h> #include <QVTKWidget.h> #include <vtkBMPReader.h> #include <vtkJPEGReader.h> #include <vtkImageActor.h> #include <vtkEventQtSlotConnect.h> #include "vtkCommand.h" #include <vtkOutputWindow.h> #include "vtkSmartPointer.h" //為了能夠使用vtk添加代碼 #include "vtkAutoInit.h" VTK_MODULE_INIT(vtkRenderingOpenGL2); // VTK was built with vtkRenderingOpenGL2 VTK_MODULE_INIT(vtkInteractionStyle); using namespace std; class vtkImageViewer2; class vtkRenderer; class vtkEventQtSlotConnect; class QVTKWidget; class VTKReadJpg_InQT_Test : public QMainWindow { Q_OBJECT public: VTKReadJpg_InQT_Test(QWidget* parent = Q_NULLPTR); private: Ui::VTKReadJpg_InQT_TestClass ui; private slots: void onOpenSlot(void); private: vtkSmartPointer<vtkImageViewer2> m_pImageViewer; vtkSmartPointer<vtkRenderer> m_pRenderer; //QVTKWidget m_qvtkWidget; };
VTKReadJpg_InQT_Test.cpp

#include "VTKReadJpg_InQT_Test.h" VTKReadJpg_InQT_Test::VTKReadJpg_InQT_Test(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); m_pImageViewer = vtkSmartPointer<vtkImageViewer2>::New(); m_pRenderer = vtkSmartPointer<vtkRenderer>::New(); //設置qvtkWidget的渲染器 ui.qvtkWidget->GetRenderWindow()->AddRenderer(m_pRenderer); //m_qvtkWidget.GetRenderWindow()->AddRenderer(m_pRenderer); //連接信號和槽 // connect(ui.pushButton, SIGNAL(clicked(bool)), this, SLOT(onOpenSlot())); } void VTKReadJpg_InQT_Test::onOpenSlot(void) { QString FileInstruction; FileInstruction = "Image Files(*.jpg *.jpeg);;All(*.*)"; QDir FileDir; //QString fileName = QFileDialog::getOpenFileName(this, QString(tr("打開圖像")), "", File); QString fileName = QFileDialog::getOpenFileName(this, "please choose an image file", "", FileInstruction); if (fileName.isEmpty() == true) { cout << "error" << endl; return; } //顯示路徑 QFileInfo OpenFileInfo; OpenFileInfo = QFileInfo(fileName); QString OpenFilePath = OpenFileInfo.filePath(); ui.lineEdit->setText(OpenFilePath); // 支持帶中文路徑的讀取 QByteArray ba = fileName.toLocal8Bit(); const char* fileName_str = ba.data(); //使用vtkJPEGReader讀取圖像 vtkSmartPointer<vtkJPEGReader>reader = vtkSmartPointer<vtkJPEGReader>::New(); reader->SetFileName(fileName_str); //reader->SetFileName("D:\\Pictures\\1.jpg"); reader->Update(); //將reader 的輸出作為 viewer的輸入,並且設置Viewer與渲染器的關聯 //m_pImageViewer->SetInputData(reader->GetOutput()); m_pImageViewer->SetInputData(reader->GetOutput()); m_pImageViewer->UpdateDisplayExtent(); m_pImageViewer->SetRenderWindow(ui.qvtkWidget->GetRenderWindow()); m_pImageViewer->SetRenderer(m_pRenderer); m_pImageViewer->SetupInteractor(ui.qvtkWidget->GetRenderWindow()->GetInteractor()); m_pImageViewer->SetSliceOrientationToXY();//默認就是這個方向 m_pImageViewer->GetImageActor()->InterpolateOff(); m_pRenderer->ResetCamera(); m_pRenderer->DrawOn(); ui.qvtkWidget->SetRenderWindow(m_pImageViewer->GetRenderWindow()); ui.qvtkWidget->GetRenderWindow()->Render(); }
main.cpp

#include "VTKReadJpg_InQT_Test.h" #include <QtWidgets/QApplication> int main(int argc, char *argv[]) { vtkOutputWindow::SetGlobalWarningDisplay(0); QApplication a(argc, argv); VTKReadJpg_InQT_Test w; w.show(); return a.exec(); }
7、運行出現的結果
四、出現問題
工程建立的過程出現了以下的幾個問題:
1-在單獨打開的QT designer里面可以找到 QVTKWidget, 但是VS打開的QT designer( 也就是我們打開的ui文件出現的界面)里面找不到QVTKWidget.
解決辦法:參考博客:在QtDesigner中添加QVTKWidget
1.1這個時候首先我們先要檢查有沒有添加.dll文件:
找到VTK的prefix路徑里面,也就是安裝VTK時候CMake里面我們選擇的PREFIX路徑。
這里我再次介紹一下我的文件夾:
1-VTK-8.2.0 | VTK下載以后的解壓文件夾 |
2-VTK-install | VTK在Cmake的時候,選擇的編譯之后二進制文件的文件夾 |
3-VTK-prefix | 在Cmake時候,選擇的PREFIX文件夾 |
其在VTK安裝中對應的位置如圖:
接下來讓我們回歸正題:
找到QVTKWidget.dll文件:
復制到下面文件夾(注意這里需要和你的電腦版本相匹配,我需要使用的是VS2019是64位,所以選擇 msvc2017_64,所以選擇了這個文件夾):
1.2然后在打開 ui界面里面點擊:
幫助-》關於插件-》刷新
多嘗試幾次
2、在ui界面已經定義的控件,在cpp里面不能調用
這個方法在上面一個博客里面已經講過了
3、無法解析的外部符號
這個時候找到了一個相同的帖子,和我的情況是完全一樣的:
https://bbs.csdn.net/topics/391908935?page=1
別人說是鏈接的問題。
所以我重新更新了一遍vtk屬性表里面的鏈接器-》輸入-》附加依賴項里面的.lib列表
這個問題就沒有出現了.
不過這個時候也要注意,也有可能是你的vtk在安裝的時候沒有完全勾選與QT有關的選項,所以導致有的.lib文件沒有生成。
遇到這種情況大家應該想一想是不是自己的屬性表配置有問題或者是不全
4、運行出現了版本警告
這個時候我為了不顯示,使用了下面的代碼注釋了警告:
//添加頭文件 #include <vtkOutputWindow.h> //在main.cpp的main函數開頭添加 vtkOutputWindow::SetGlobalWarningDisplay(0);
5、再次運行發現什么反應都沒有
經過檢查發現是我因為我把所有警告注釋掉了,所以沒有生成程序界面,也沒有任何反應。
警告如下:
為了解決第三個警告,添加了如下的代碼(實際上為了在VS里面使用VTK,下面的代碼是最好要添加的)
#include "vtkAutoInit.h" VTK_MODULE_INIT(vtkRenderingOpenGL2); // VTK was built with vtkRenderingOpenGL2 VTK_MODULE_INIT(vtkInteractionStyle);
6、在打開的QT designer里面發現插件QVTKWidget加載失敗
這個我重新打開就好了,也不知道為什么,很迷。
五、一點體會
感覺怎么說呢,本來想着從網上借鑒一下程序,結果發現各種錯誤層出不窮,搞的自己筋疲力盡,不過好在程序終於跑出來了,不知道別人有沒有我這么艱難,起碼我是感覺自己快吐了。
六、參考鏈接
一、程序來源:程序
三、no override found for vtkImageSliceMapper
四、ui界面有控件,但是cpp里面顯示沒有成員(注釋:無法使用控件)