前言

  前面编译好了Qt5.9.3+VS2017x64+VTK8.2的开发环境,但是Qt结合VTK没有。
  本篇Qt融合VTK,搭建基础Qt界面搭载VTK显示引擎的模板Demo。

 

Demo

  QVTKWidget
  

  QVTKWidget+MyVTKWidget
  

 

注意

  这是上一篇install的结果:
  

 

建立模板工程(QVTKWidget.dll方式)

步骤一:建立vtkDemo工程

  略

步骤二:模块化

  文件夹modules,老规矩:
  

  建立模块文件夹:
  

  建立vtkWIdget.pri
  

  工程包含pri:
  

  建立VTKWidget界面类,方便提升:
  

步骤三:引入vtk的库和开发环境

  先把install复制过来,标记好qt和msvc版本,为了以后多版本vtk预留(能就别少,作为代码模块集合):
  

  添加进pri:
  直接从文件夹复制进入pri,会是路径,再修改:
  

INCLUDEPATH += $$PWD
DEPENDPATH += $$PWD HEADERS += \
$$PWD/VTKWidget.h SOURCES += \
$$PWD/VTKWidget.cpp FORMS += \
$$PWD/VTKWidget.ui # vtk库包含
INCLUDEPATH += $$PWD/vtk-8.2.0-msvc2015x64-install/include \
$$PWD/vtk-8.2.0-msvc2015x64-install/include/vtk-8.2
LIBS += -L$$PWD/vtk-8.2.0-msvc2015x64-install/lib
LIBS += -lvtkzlib-8.2 \
-lvtkChartsCore-8.2 \
-lvtkCommonColor-8.2 \
-lvtkCommonComputationalGeometry-8.2 \
-lvtkCommonCore-8.2 \
-lvtkCommonDataModel-8.2 \
-lvtkCommonExecutionModel-8.2 \
-lvtkCommonMath-8.2 \
-lvtkCommonMisc-8.2 \
-lvtkCommonSystem-8.2 \
-lvtkCommonTransforms-8.2 \
-lvtkDICOMParser-8.2 \
-lvtkDomainsChemistry-8.2 \
-lvtkDomainsChemistryOpenGL2-8.2 \
-lvtkdoubleconversion-8.2 \
-lvtkexodusII-8.2 \
-lvtkexpat-8.2 \
-lvtkFiltersAMR-8.2 \
-lvtkFiltersCore-8.2 \
-lvtkFiltersExtraction-8.2 \
-lvtkFiltersFlowPaths-8.2 \
-lvtkFiltersGeneral-8.2 \
-lvtkFiltersGeneric-8.2 \
-lvtkFiltersGeometry-8.2 \
-lvtkFiltersHybrid-8.2 \
-lvtkFiltersHyperTree-8.2 \
-lvtkFiltersImaging-8.2 \
-lvtkFiltersModeling-8.2 \
-lvtkFiltersParallel-8.2 \
-lvtkFiltersParallelImaging-8.2 \
-lvtkFiltersPoints-8.2 \
-lvtkFiltersProgrammable-8.2 \
-lvtkFiltersSelection-8.2 \
-lvtkFiltersSMP-8.2 \
-lvtkFiltersSources-8.2 \
-lvtkFiltersStatistics-8.2 \
-lvtkFiltersTexture-8.2 \
-lvtkFiltersTopology-8.2 \
-lvtkFiltersVerdict-8.2 \
-lvtkfreetype-8.2 \
-lvtkGeovisCore-8.2 \
-lvtkgl2ps-8.2 \
-lvtkglew-8.2 \
-lvtkGUISupportQt-8.2 \
-lvtkGUISupportQtSQL-8.2 \
-lvtkhdf5_hl-8.2 \
-lvtkhdf5-8.2 \
-lvtkImagingColor-8.2 \
-lvtkImagingCore-8.2 \
-lvtkImagingFourier-8.2 \
-lvtkImagingGeneral-8.2 \
-lvtkImagingHybrid-8.2 \
-lvtkImagingMath-8.2 \
-lvtkImagingMorphological-8.2 \
-lvtkImagingSources-8.2 \
-lvtkImagingStatistics-8.2 \
-lvtkImagingStencil-8.2 \
-lvtkInfovisCore-8.2 \
-lvtkInfovisLayout-8.2 \
-lvtkInteractionImage-8.2 \
-lvtkInteractionStyle-8.2 \
-lvtkInteractionWidgets-8.2 \
-lvtkIOAMR-8.2 \
-lvtkIOAsynchronous-8.2 \
-lvtkIOCityGML-8.2 \
-lvtkIOCore-8.2 \
-lvtkIOEnSight-8.2 \
-lvtkIOExodus-8.2 \
-lvtkIOExport-8.2 \
-lvtkIOExportOpenGL2-8.2 \
-lvtkIOExportPDF-8.2 \
-lvtkIOGeometry-8.2 \
-lvtkIOImage-8.2 \
-lvtkIOImport-8.2 \
-lvtkIOInfovis-8.2 \
-lvtkIOLegacy-8.2 \
-lvtkIOLSDyna-8.2 \
-lvtkIOMINC-8.2 \
-lvtkIOMovie-8.2 \
-lvtkIONetCDF-8.2 \
-lvtkIOParallel-8.2 \
-lvtkIOParallelXML-8.2 \
-lvtkIOPLY-8.2 \
-lvtkIOSegY-8.2 \
-lvtkIOSQL-8.2 \
-lvtkIOTecplotTable-8.2 \
-lvtkIOVeraOut-8.2 \
-lvtkIOVideo-8.2 \
-lvtkIOXML-8.2 \
-lvtkIOXMLParser-8.2 \
-lvtkjpeg-8.2 \
-lvtkjsoncpp-8.2 \
-lvtklibharu-8.2 \
-lvtklibxml2-8.2 \
-lvtkLocalExample-8.2 \
-lvtklz4-8.2 \
-lvtklzma-8.2 \
-lvtkmetaio-8.2 \
-lvtkNetCDF-8.2 \
-lvtkogg-8.2 \
-lvtkParallelCore-8.2 \
-lvtkpng-8.2 \
-lvtkproj-8.2 \
-lvtkpugixml-8.2 \
-lvtkRenderingAnnotation-8.2 \
-lvtkRenderingContext2D-8.2 \
-lvtkRenderingContextOpenGL2-8.2 \
-lvtkRenderingCore-8.2 \
-lvtkRenderingFreeType-8.2 \
-lvtkRenderingGL2PSOpenGL2-8.2 \
-lvtkRenderingImage-8.2 \
-lvtkRenderingLabel-8.2 \
-lvtkRenderingLOD-8.2 \
-lvtkRenderingOpenGL2-8.2 \
-lvtkRenderingQt-8.2 \
-lvtkRenderingVolume-8.2 \
-lvtkRenderingVolumeOpenGL2-8.2 \
-lvtksqlite-8.2 \
-lvtksys-8.2 \
-lvtktheora-8.2 \
-lvtktiff-8.2 \
-lvtkverdict-8.2 \
-lvtkViewsContext2D-8.2 \
-lvtkViewsCore-8.2 \
-lvtkViewsGeovis-8.2 \
-lvtkViewsInfovis-8.2 \
-lvtkViewsQt-8.2 # win平台的复制dll
win32{
# copy vtk bin
src_file = $$PWD/vtk-8.2.0-msvc2015x64-install/bin/*
dst_file = $$OUT_PWD
target_file = $$DESTDIR
src_file ~= s,/,\\,g
dst_file ~= s,/,\\,g
target_file ~= s,/,\\,g
system(xcopy $$src_file $$dst_file /y /s/q/e)
system(xcopy $$src_file $$target_file /y /s/q/e)
}

  至此,运行环境引入好了。

步骤四:vkt引擎融入Qt界面

  这里我们是直接通过QVTKWidget.h头文件和其lib、dll的方式引入:
  

 

建立模板工程(MyVTKWidget.cpp方式)

  为了最大化兼容代码,这里QVTKWidget.dll就不动了,QVTKWidget源码里面实际是跟osgWidget一样,映射了窗口对于渲染器的操作,这里我们可以直接拿过来改个名字即可,所以先找到QVTKWidget.h和QVTKWIdget.cpp的源码,改成MyVTKWidget.h,MyVTKWidget.cpp:
  

  复制改名:
  

  加入源码:
  

  修改里面的类名为MyVTKWidget,注意修改头文件宏:
  

  编译通过,修改加入之后,出现一些错误:
  

  这是因为代码默认定义了宏是导出dll的,所以需要修改,先去掉类的导出dll宏,然后编译,出错如下:
  

  检查:
  

  点开查看:
  

  是因为这个类在这个库里面压根没有导出来cpp。
  现在直接反过来去添加导出,修改源码(测试加头文件定义宏也报错,直接加入导出的代码吧):
  

  然后重新编译:
  

  安装并将库引过去替换试一试:
  

  再次编译,解决了库定义的问题,还剩一个问题:
  

  还是往回退到VS2017去搜索,搜索不到,这就是windows的函数,连接到对应的库就好了:
  

  编译成功,运行失败:
  
  怀疑是没包含dll,下面直接exe进行探测:
  
  先补完qt的库:
  
  然后点击运行:
  
  是因为更新了这个lib,但是没有更新对应的dll过来:
  
  Ok了,运行起来了,使用修改 源码大法可以 搞定,这样以后做其他的对映射操作就很方便了:
  
  运行起来一个黑色一个白色:
  

  去掉父类,测试左侧这种就是白色的。
  为了确保可靠性,咱们还需要确认下,黑色和白色是否都是正常的,黑色肯定是正常的,写个常规代码:
  跑起来后:
  

  怀疑是哪个地方没有跑,导致初始化没有黑色,但是有场景的时候不影响。

 

建立模板工程(MyVTKWidget.cpp方式,失败,仅供参考)

  为了最大化兼容代码,这里QVTKWidget.dll就不动了,QVTKWidget源码里面实际是跟osgWidget一样,映射了窗口对于渲染器的操作,这里我们可以直接拿过来改个名字即可,所以先找到QVTKWidget.h和QVTKWIdget.cpp的源码,改成MyVTKWidget.h,MyVTKWidget.cpp:
  

  复制改名:
  

  加入源码:
  

  修改里面的类名为MyVTKWidget,注意修改头文件宏:
  

  编译通过,修改加入之后,出现一些错误:
  

  这是因为代码默认定义了宏是导出dll的,所以需要修改,先去掉类的导出dll宏,然后编译,出错如下:
  

  检查是需要包含win:
  

  继续编译:
  
  #error: “No Target Architecture”
  

  直接返回vs2017编译源码,查找编译的时候定义了哪些宏:
  

  

WIN32
_WINDOWS
NDEBUG
QT_NO_DEBUG
_CRT_SECURE_NO_DEPRECATE
_CRT_NONSTDC_NO_DEPRECATE
_CRT_SECURE_NO_WARNINGS
_SCL_SECURE_NO_DEPRECATE
_SCL_SECURE_NO_WARNINGS
VTK_IN_VTK
QT_WIDGETS_LIB
QT_GUI_LIB
QT_CORE_LIB
QT_UIPLUGIN_LIB
CMAKE_INTDIR="Release"
QVTKWidgetPlugin_EXPORTS

  此方式行不通!!!
  换个方式,退回去

 

注意

  对比下osg和vtk的库大小:
  
  

 

源码

VTKWidget.h

#ifndef VTKWIDGET_H
#define VTKWIDGET_H #include <QWidget>
#include "QVTKWidget.h"
#include "MyVTKWidget.h" #include "vtkSphereSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkInteractorStyleTrackballCamera.h" #include "vtkOutputWindow.h"
#include "vtkAutoInit.h"
//VTK_MODULE_INIT(vtkRenderingOpenGL);
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle); namespace Ui {
class VTKWidget;
} class VTKWidget : public QWidget
{
Q_OBJECT public:
explicit VTKWidget(QWidget *parent = 0);
~VTKWidget(); protected:
void initControl(); protected:
void createSphere(QVTKWidget *pVTKWidget); // 临时代码,忽略代码规则
void createSphere(MyVTKWidget *pVTKWidget); // 临时代码,忽略代码规则 protected:
void resizeEvent(QResizeEvent *event); private:
Ui::VTKWidget *ui; private:
QVTKWidget *_pQVTKWidget;
MyVTKWidget *_pMyVTKWidget;
}; #endif // VTKWIDGET_H

VTKWidget.cpp

#include "VTKWidget.h"
#include "ui_VTKWidget.h" #include <QDebug>
#include <QDateTime>
//#define LOG qDebug()<<__FILE__<<__LINE__
//#define LOG qDebug()<<__FILE__<<__LINE__<<__FUNCTION__
//#define LOG qDebug()<<__FILE__<<__LINE__<<QThread()::currentThread()
//#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd")
#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") // QtCreator在msvc下设置编码也或有一些乱码,直接一刀切,避免繁琐的设置
#define MSVC
#ifdef MSVC
#define QSTRING(s) QString::fromLocal8Bit(s)
#else
#define QSTRING(s) QString(s)
#endif VTKWidget::VTKWidget(QWidget *parent)
: QWidget(parent),
ui(new Ui::VTKWidget),
_pQVTKWidget(0),
_pMyVTKWidget(0)
{
ui->setupUi(this); initControl();
} VTKWidget::~VTKWidget()
{
delete ui;
} void VTKWidget::initControl()
{ // 下面二选一,注意:这里必须在new之前设置好,new QVTKWidget窗口之后是无效的
vtkOutputWindow::GlobalWarningDisplayOff(); // 两段代码效果应该一致
vtkOutputWindow::SetGlobalWarningDisplay(0); // 设置消息登记显示,0-都不显示 _pQVTKWidget = new QVTKWidget(this);
createSphere(_pQVTKWidget); _pMyVTKWidget = new MyVTKWidget(this);
createSphere(_pMyVTKWidget);
} void VTKWidget::createSphere(QVTKWidget *pVTKWidget)
{
// 1. 创建球体数据
vtkSphereSource* sphere = vtkSphereSource::New();
sphere->SetRadius(1.0); // 球体半径
sphere->SetThetaResolution(30); // 纬线方向分辨率
sphere->SetPhiResolution(30); // 经线方向分辨率 // 2. 创建映射器(连接数据与渲染)
vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
mapper->SetInputConnection(sphere->GetOutputPort()); // 3. 创建演员(设置显示属性)
vtkActor* actor = vtkActor::New();
actor->SetMapper(mapper);
actor->GetProperty()->SetColor(0.3, 0.6, 0.9); // 蓝色球体 // 4. 创建渲染器并添加球体
vtkRenderer* renderer = vtkRenderer::New();
renderer->AddActor(actor);
renderer->SetBackground(0.1, 0.1, 0.1); // 深灰色背景 // 5. 关联到QVTKWidget的渲染窗口
pVTKWidget->GetRenderWindow()->AddRenderer(renderer); // 6. 设置交互(支持鼠标旋转、缩放)
vtkRenderWindowInteractor* interactor = vtkRenderWindowInteractor::New();
interactor->SetRenderWindow(pVTKWidget->GetRenderWindow());
interactor->SetInteractorStyle(vtkInteractorStyleTrackballCamera::New());
interactor->Initialize();
} void VTKWidget::createSphere(MyVTKWidget *pVTKWidget)
{
// 1. 创建球体数据
vtkSphereSource* sphere = vtkSphereSource::New();
sphere->SetRadius(1.0); // 球体半径
sphere->SetThetaResolution(30); // 纬线方向分辨率
sphere->SetPhiResolution(30); // 经线方向分辨率 // 2. 创建映射器(连接数据与渲染)
vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
mapper->SetInputConnection(sphere->GetOutputPort()); // 3. 创建演员(设置显示属性)
vtkActor* actor = vtkActor::New();
actor->SetMapper(mapper);
actor->GetProperty()->SetColor(0.3, 0.6, 0.9); // 蓝色球体 // 4. 创建渲染器并添加球体
vtkRenderer* renderer = vtkRenderer::New();
renderer->AddActor(actor);
renderer->SetBackground(0.1, 0.1, 0.1); // 深灰色背景 // 5. 关联到QVTKWidget的渲染窗口
pVTKWidget->GetRenderWindow()->AddRenderer(renderer); // 6. 设置交互(支持鼠标旋转、缩放)
vtkRenderWindowInteractor* interactor = vtkRenderWindowInteractor::New();
interactor->SetRenderWindow(pVTKWidget->GetRenderWindow());
interactor->SetInteractorStyle(vtkInteractorStyleTrackballCamera::New());
interactor->Initialize();
} void VTKWidget::resizeEvent(QResizeEvent *event)
{
if(_pQVTKWidget)
{
_pQVTKWidget->setGeometry(rect().x(), rect().y(), rect().width() / 2 - 10, rect().height());
}
if(_pMyVTKWidget)
{
_pMyVTKWidget->setGeometry(rect().width() / 2 + 10, rect().y(), rect().width() / 2 - 10, rect().height()); }
}
 

工程模板v1.0.0

  

 

入坑

入坑一:运行渲染窗口弹出8.1remove

问题

  出错点击关闭,提示截图图下:
  

  

尝试

  添加头文件
  

  初始化
  

  然后结果:
  

  调试窗口还是存在,关闭或者设置等级0,即可消息窗口输出即可。

解决

  头文件
  

#include "vtkAutoInit.h"

  初始化
  

VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);

  添加关闭打印信息输出或者设置输出等级
  

  

// 下面二选一,注意:这里必须在new之前设置好,new QVTKWidget窗口之后是无效的
vtkOutputWindow::GlobalWarningDisplayOff(); // 两段代码效果应该一致
vtkOutputWindow::SetGlobalWarningDisplay(0); // 设置消息登记显示,0-都不显示

  

VTK开发笔记(二):Qt5.9.3+VS2017x64+VTK8.2创建兼容dll和嵌入源码窗口两种方式的Qt嵌入VTK8.2模板Demo的更多相关文章

  1. 仿酷狗音乐播放器开发日志二十七 用ole为窗体增加文件拖动功能(附源码)

    转载请说明原出处,谢谢~~ 中秋到了,出去玩了几天.今天把仿酷狗程序做了收尾,已经开发完成了,下一篇博客把完结的情况说一下.在这篇博客里说一下使用OLE为窗体增加文件拖拽的功能.使用播放器,我更喜欢直 ...

  2. java制作二维码的两种方式

    原博:http://www.importnew.com/15028.html Zebra Crossing(ZXing)是一个很棒的,几乎可以在所有平台(Android.JavaSE.iPhone.R ...

  3. 【代码笔记】iOS-向服务器传JSON数据的两种方式

    一,代码. - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. ...

  4. Django开发笔记二

    Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.xadmin添加主题.修改标题页脚和收起左侧菜单 # ...

  5. ASP.NET 生成二维码(采用ThoughtWorks.QRCode和QrCode.Net两种方式)

    最近做项目遇到生成二维码的问题,发现网上用的最多的是ThoughtWorks.QRCode和QrCode.Net两种方式.访问官网看着例子写了两个Demo,使用过程中发现两个都挺好用的,Thought ...

  6. 怎样在Android开发中FPS游戏实现的两种方式比较

    怎样在Android开发中FPS游戏实现的两种方式比较 如何用Android平台开发FPS游戏,其实现过程有哪些方法,这些方法又有哪些不同的地方呢?首先让我们先了解下什么是FPS 英文名:FPS (F ...

  7. jQuery中开发插件的两种方式

    jQuery中开发插件的两种方式(附Demo) 做web开发的基本上都会用到jQuery,jQuery插件开发两种方式:一种是类扩展的方式开发插件,jQuery添加新的全局函数(jQuery的全局函数 ...

  8. [Android] Android ViewPager 中加载 Fragment的两种方式 方式(二)

    接上文: https://www.cnblogs.com/wukong1688/p/10693338.html Android ViewPager 中加载 Fragmenet的两种方式 方式(一) 二 ...

  9. mysql批量更新的两种方式效率试验<二>

    Mysql两种批量更新的对比 简介: mysql搭载mybits框架批量更新有两种方式,一种是在xml中循环整个update语句,中间以‘:’隔开,还有一种是使用case when 变相实现批量更新, ...

  10. 自学Linux Shell9.4-基于Red Hat系统工具包存在两种方式之二:源码包

    点击返回 自学Linux命令行与Shell脚本之路 9.4-基于Red Hat系统工具包存在两种方式之二:源码包 本节主要介绍基于Red Had的系统(测试系统centos) 1. 工具包存在两种方式 ...

随机推荐

  1. linux系统磁盘快速创建多个分区

    # 创建分区 [root@centos7 ~]# cat parted.sh parted --script /dev/sdb \ mklabel gpt \ mkpart primary 1MiB ...

  2. 防抖ref如何在vue中被定义

    本文由 ChatMoney团队出品 为什么ref要实现防抖 在vue的开发过程中,我们通常会使用到ref,但在我们需要对一个频繁的赋值操作做防抖操作时,我们通常只能通过编写一个独立的防抖函数来实现,这 ...

  3. 基于Casbin的ABAC授权模型设计与开发踩坑实录

    本文分享自天翼云开发者社区<基于Casbin的ABAC授权模型设计与开发踩坑实录>,作者:upclose 最近因项⽬需求,需要寻求⼀个好⽤强⼤的权限管理⽅案.天翼云安全实验室经过仔细调研, ...

  4. C#.Net筑基-优雅LINQ的查询艺术

    Linq(Language Integrated Query,集成查询语言),顾名思义就是用来查询数据的一种语言(可以看作是一组功能.框架特性的集合).在.NETFramework3.5(大概2007 ...

  5. 11-3 MySQL 中对于 PowerDesigner 的使用

    11-3 MySQL 中对于 PowerDesigner 的使用 @ 目录 11-3 MySQL 中对于 PowerDesigner 的使用 1. PowerDesigner的使用 1.1 开始界面 ...

  6. 8.Java Spring框架源码分析-IOC-调用BeanFactoryPostProcessor的postProcess方法

    目录 1. 要研究的代码 2. 处理BeanDefinitionRegistryPostProcessor类型的PostProcessor 2.1. 当前bean工厂是BeanDefinitionRe ...

  7. ZanProxy使用方式

    参考官方文档https://youzan.github.io/zan-proxy/book/ 前提安装node安装openssl 安装 npm i -g zan-proxy 启动 zan-proxy ...

  8. Java锁这样用,从单机到分布式一步到位

    Java锁这样用,从单机到分布式一步到位 单机锁已经不够用了?分布式系统中如何保证数据安全?今天我们来聊聊从单机锁到分布式锁的完整解决方案,最后用一个注解就能搞定所有锁的问题! 为什么需要锁? 在多线 ...

  9. Efficient C++ 阅读笔记

    Efficient C++ 阅读笔记 技术要点: reference 永远没有成为NULL的机会 如果出现 那么请隔离那个写出这种代码的程序员 在写程序的时候为了系统的健壮性能,一定要测试 指针的可用 ...

  10. 干翻 Typora!MilkUp:完全免费的桌面端 Markdown 编辑器!

    不知道大家平时写 markdown 都是用什么软件呢?是多端同步的印象笔记?还是 vscode 内置编辑器?还是大名鼎鼎的 typora?你不会用记事本在写 markdown 吧? 不过据说微软已经把 ...