一、前言
今天实现的主要功能是通过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平台配置的,如果发现不对要更改) |
二、参考博客
博客:https://blog.csdn.net/qq_41969439/article/details/88666629?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
三、工程建立
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_OBJECTpublic: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加载失败
这个我重新打开就好了,也不知道为什么,很迷。
五、一点体会
感觉怎么说呢,本来想着从网上借鉴一下程序,结果发现各种错误层出不穷,搞的自己筋疲力尽,不过好在程序终于跑出来了,不知道别人有没有我这么艰难,起码我是感觉自己快吐了。
六、参考链接
一、程序来源:程序
二、在QT designer 添加QVTKWidget
三、no override found for vtkImageSliceMapper
四、ui界面有控件,但是cpp里面显示没有成员(注释:无法使用控件)