> 技术文档 > QT中使用VTK_qt vtk是啥

QT中使用VTK_qt vtk是啥

VTK (Visualization Toolkit) 是一个强大的开源三维可视化库,而QT是一个流行的跨平台GUI框架。将两者结合可以创建功能丰富的科学可视化应用程序。

一、环境准备

首先确保已安装:

  • QT (5.9或更高版本)

  • VTK (9.0或更高版本)

  • CMake (构建工具)

二、基本集成方法

1. 使用QVTKOpenGLNativeWidget(推荐方式)

#include #include #include #include #include #include #include #include int main(int argc, char** argv){ // 设置QT应用 QApplication app(argc, argv); // 设置OpenGL版本和格式 QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat()); // 创建QT窗口和VTK部件 QMainWindow mainWindow; QVTKOpenGLNativeWidget* vtkWidget = new QVTKOpenGLNativeWidget(&mainWindow); // 创建VTK管线 vtkNew cone; vtkNew mapper; mapper->SetInputConnection(cone->GetOutputPort()); vtkNew actor; actor->SetMapper(mapper); vtkNew renderer; renderer->AddActor(actor); vtkWidget->renderWindow()->AddRenderer(renderer); // 设置窗口并显示 mainWindow.setCentralWidget(vtkWidget); mainWindow.resize(800, 600); mainWindow.show(); return app.exec();}

2. 使用QVTKOpenGLWidget (旧版方式)

#include // 其他包含与上面类似// 使用方式与QVTKOpenGLNativeWidget类似

三、Make配置 

CMake配置示例

cmake_minimum_required(VERSION 3.12)project(VTK_QT_Example)find_package(Qt5 REQUIRED COMPONENTS Widgets)find_package(VTK REQUIRED)add_executable(vtk_qt_example main.cpp)target_link_libraries(vtk_qt_example PRIVATE Qt5::Widgets ${VTK_LIBRARIES})

或者 QMake配置示例(.pro文件)

QT += core guigreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += c++17# You can make your code fail to compile if it uses deprecated APIs.# In order to do so, uncomment the following line.#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0SOURCES += \\ main.cpp \\ mainwindow.cppHEADERS += \\ mainwindow.hFORMS += \\ mainwindow.ui# Unix/Linux 配置unix { # 假设 VTK 安装在 /usr 目录下 VTK_DIR = /usr/lib/cmake/vtk-9.2 INCLUDEPATH += $$system(/usr/lib/vtk-9.2/include/vtk-9.2) LIBS += -L$$system(/usr/lib/vtk-9.2/lib) LIBS += -lGL}# Windows 配置win32 { INCLUDEPATH += $$PWD/\'../../../../Program Files/VTK/include/vtk-9.2\' DEPENDPATH += $$PWD/\'../../../../Program Files/VTK/include/vtk-9.2\' LIBS += -lopengl32}win32:CONFIG(release, debug|release):{LIBS += -L$$PWD/\'../../../../Program Files/VTK/lib/\'}else:win32:CONFIG(debug, debug|release): {LIBS += -L$$PWD/\'../../../../Program Files/VTK/lib/\'}else:unix:{LIBS += -L$$PWD/\'../../../../Program Files/VTK/lib/\'LIBS += -lGL}# Default rules for deployment.qnx: target.path = /tmp/$${TARGET}/binelse: unix:!android: target.path = /opt/$${TARGET}/bin!isEmpty(target.path): INSTALLS += target# 必需的核心 VTK 库LIBS += -lvtksys-9.2LIBS += -lvtkCommonColor-9.2LIBS += -lvtkCommonCore-9.2LIBS += -lvtkCommonDataModel-9.2LIBS += -lvtkFiltersCore-9.2LIBS += -lvtkInteractionStyle-9.2LIBS += -lvtkRenderingCore-9.2LIBS += -lvtkRenderingOpenGL2-9.2LIBS += -lvtkViewsQt-9.2LIBS += -lvtkGUISupportQt-9.2LIBS += -lvtkRenderingAnnotation-9.2# 可选: 用于数据处理和可视化的附加库LIBS += -lvtkFiltersSources-9.2LIBS += -lvtkFiltersGeneral-9.2LIBS += -lvtkIOCore-9.2LIBS += -lvtkIOXML-9.2

四、创建基本QT-VTK应用

1 创建QT项目

创建一个基本的QT Widgets Application项目。

2 修改main.cpp和mainwindow.h/mainwindow.cpp文件

 mainwindow.h

#ifndef MAINWINDOW_H#define MAINWINDOW_H#include // VTK 头文件#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Qt VTK 集成组件#include  // 或 QVTKOpenGLWidgetQT_BEGIN_NAMESPACEnamespace Ui {class MainWindow;}QT_END_NAMESPACEclass MainWindow : public QMainWindow{ Q_OBJECTpublic: MainWindow(QWidget *parent = nullptr); ~MainWindow();public slots: void setupColorMap(int scheme = 0);private: void setupVTK(); void createSampleData(); void createToolBar(); QVTKOpenGLNativeWidget *vtkWidget; vtkRenderWindow *renderWindow; vtkRenderer *renderer; vtkUnstructuredGrid *unstructuredGrid; vtkActor *actor; vtkDataSetMapper *mapper; vtkScalarBarActor *scalarBar;private: Ui::MainWindow *ui;};#endif // MAINWINDOW_H

mainwindow.cpp

#include \"mainwindow.h\"#include \"ui_mainwindow.h\"#include #include #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow){ ui->setupUi(this); setWindowTitle(\"VTK Stress Cloud\"); resize(800, 600); createToolBar(); // 创建中央部件和布局 QWidget *centralWidget = new QWidget(this); QVBoxLayout *layout = new QVBoxLayout(centralWidget); // 创建 VTK 部件 vtkWidget = new QVTKOpenGLNativeWidget(centralWidget); layout->addWidget(vtkWidget); setCentralWidget(centralWidget); // 初始化 VTK setupVTK();}MainWindow::~MainWindow(){ // 清理 VTK 对象 if (renderWindow) renderWindow->Delete(); if (renderer) renderer->Delete(); if (unstructuredGrid) unstructuredGrid->Delete(); if (actor) actor->Delete(); if (mapper) mapper->Delete(); if (scalarBar) scalarBar->Delete(); delete ui;}void MainWindow::setupVTK(){ // 创建渲染窗口和渲染器 renderWindow = vtkGenericOpenGLRenderWindow::New(); vtkWidget->setRenderWindow(renderWindow); renderer = vtkRenderer::New(); renderWindow->AddRenderer(renderer); //添加交互功能 vtkNew style; renderWindow->GetInteractor()->SetInteractorStyle(style); // 创建示例数据 createSampleData(); // 设置背景色 vtkNew colors; renderer->SetBackground(colors->GetColor3d(\"SlateGray\").GetData()); // 重置相机并渲染 renderer->ResetCamera(); renderWindow->Render();}void MainWindow::createSampleData(){ // 1. 创建点数据 (节点坐标) vtkNew points; points->InsertNextPoint(0.0, 0.0, 0.0); points->InsertNextPoint(1.0, 0.0, 0.0); points->InsertNextPoint(0.0, 1.0, 0.0); points->InsertNextPoint(1.0, 1.0, 0.0); points->InsertNextPoint(0.5, 0.5, 0.0); // 中心点 // 2. 创建非结构化网格 unstructuredGrid = vtkUnstructuredGrid::New(); unstructuredGrid->SetPoints(points); // 创建三角形单元 vtkNew triangle1; triangle1->GetPointIds()->SetId(0, 0); triangle1->GetPointIds()->SetId(1, 1); triangle1->GetPointIds()->SetId(2, 4); vtkNew triangle2; triangle2->GetPointIds()->SetId(0, 1); triangle2->GetPointIds()->SetId(1, 3); triangle2->GetPointIds()->SetId(2, 4); vtkNew triangle3; triangle3->GetPointIds()->SetId(0, 3); triangle3->GetPointIds()->SetId(1, 2); triangle3->GetPointIds()->SetId(2, 4); vtkNew triangle4; triangle4->GetPointIds()->SetId(0, 2); triangle4->GetPointIds()->SetId(1, 0); triangle4->GetPointIds()->SetId(2, 4); unstructuredGrid->InsertNextCell(triangle1->GetCellType(), triangle1->GetPointIds()); unstructuredGrid->InsertNextCell(triangle2->GetCellType(), triangle2->GetPointIds()); unstructuredGrid->InsertNextCell(triangle3->GetCellType(), triangle3->GetPointIds()); unstructuredGrid->InsertNextCell(triangle4->GetCellType(), triangle4->GetPointIds()); // 3. 创建应力数据 (节点标量数据) vtkNew stressData; stressData->SetNumberOfComponents(1); stressData->SetName(\"Stress\"); // 为每个节点添加应力值 stressData->InsertNextValue(10.0); // 节点0 stressData->InsertNextValue(20.0); // 节点1 stressData->InsertNextValue(15.0); // 节点2 stressData->InsertNextValue(25.0); // 节点3 stressData->InsertNextValue(50.0); // 中心节点4 (高应力区域) unstructuredGrid->GetPointData()->SetScalars(stressData); // 4. 创建映射器 mapper = vtkDataSetMapper::New(); mapper->SetInputData(unstructuredGrid); // 设置颜色映射范围 double range[2]; stressData->GetRange(range); mapper->SetScalarRange(range); // 5. 创建演员 actor = vtkActor::New(); actor->SetMapper(mapper); // 6. 创建标量条 scalarBar = vtkScalarBarActor::New(); scalarBar->SetLookupTable(mapper->GetLookupTable()); scalarBar->SetTitle(\"Stress (MPa)\\n\"); scalarBar->SetNumberOfLabels(5); scalarBar->SetMaximumWidthInPixels(80); scalarBar->SetMaximumHeightInPixels(200); // 7. 添加到渲染器 renderer->AddActor(actor); renderer->AddActor2D(scalarBar);}// 在主窗口类中添加:void MainWindow::createToolBar(){ QToolBar* toolBar = addToolBar(\"Controls\"); QAction* zoomInAction = new QAction(\"Zoom In\", this); QAction* zoomOutAction = new QAction(\"Zoom Out\", this); //QAction* colorMapAction = new QAction(\"Color Map\", this); toolBar->addAction(zoomInAction); toolBar->addAction(zoomOutAction); //toolBar->addAction(colorMapAction); connect(zoomInAction, &QAction::triggered, [this]() { vtkCamera* camera = vtkWidget->renderWindow()->GetRenderers()->GetFirstRenderer()->GetActiveCamera(); camera->Zoom(1.2); vtkWidget->renderWindow()->Render(); }); connect(zoomOutAction, &QAction::triggered, [this]() { vtkCamera* camera = vtkWidget->renderWindow()->GetRenderers()->GetFirstRenderer()->GetActiveCamera(); camera->Zoom(0.8); vtkWidget->renderWindow()->Render(); }); /* connect(colorMapAction, &QAction::triggered, [this]() { setupColorMap(2); vtkWidget->renderWindow()->Render(); }); */}void MainWindow::setupColorMap(int scheme){ if (!mapper) return; vtkNew lut; switch (scheme) { case 0: // 蓝到红 lut->SetHueRange(0.667, 0.0); break; case 1: // 彩虹色 lut->SetHueRange(0.0, 0.667); break; case 2: // 灰度 lut->SetHueRange(0.0, 0.0); lut->SetSaturationRange(0.0, 0.0); lut->SetValueRange(0.2, 1.0); break; case 3: // 热力图 lut->SetHueRange(0.0, 0.2); break; } lut->SetSaturationRange(1.0, 1.0); lut->SetValueRange(1.0, 1.0); lut->Build(); mapper->SetLookupTable(lut); scalarBar->SetLookupTable(lut); renderWindow->Render();}

main.cpp

#include \"mainwindow.h\"#include #include int main(int argc, char *argv[]){ // 设置 OpenGL 表面格式 QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat()); QApplication a(argc, argv); MainWindow w; w.show(); return a.exec();}

.pro

QT += core guigreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += c++17# You can make your code fail to compile if it uses deprecated APIs.# In order to do so, uncomment the following line.#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0SOURCES += \\ main.cpp \\ mainwindow.cppHEADERS += \\ mainwindow.hFORMS += \\ mainwindow.ui# Unix/Linux 配置unix { # 假设 VTK 安装在 /usr 目录下 VTK_DIR = /usr/lib/cmake/vtk-9.2 INCLUDEPATH += $$system(/usr/lib/vtk-9.2/include/vtk-9.2) LIBS += -L$$system(/usr/lib/vtk-9.2/lib) LIBS += -lGL}# Windows 配置win32 { INCLUDEPATH += $$PWD/\'../../../../Program Files/VTK/include/vtk-9.2\' DEPENDPATH += $$PWD/\'../../../../Program Files/VTK/include/vtk-9.2\' LIBS += -lopengl32}win32:CONFIG(release, debug|release):{LIBS += -L$$PWD/\'../../../../Program Files/VTK/lib/\'}else:win32:CONFIG(debug, debug|release): {LIBS += -L$$PWD/\'../../../../Program Files/VTK/lib/\'}else:unix:{LIBS += -L$$PWD/\'../../../../Program Files/VTK/lib/\'LIBS += -lGL}# Default rules for deployment.qnx: target.path = /tmp/$${TARGET}/binelse: unix:!android: target.path = /opt/$${TARGET}/bin!isEmpty(target.path): INSTALLS += target# 必需的核心 VTK 库LIBS += -lvtksys-9.2LIBS += -lvtkCommonColor-9.2LIBS += -lvtkCommonCore-9.2LIBS += -lvtkCommonDataModel-9.2LIBS += -lvtkFiltersCore-9.2LIBS += -lvtkInteractionStyle-9.2LIBS += -lvtkRenderingCore-9.2LIBS += -lvtkRenderingOpenGL2-9.2LIBS += -lvtkViewsQt-9.2LIBS += -lvtkGUISupportQt-9.2LIBS += -lvtkRenderingAnnotation-9.2# 可选: 用于数据处理和可视化的附加库LIBS += -lvtkFiltersSources-9.2LIBS += -lvtkFiltersGeneral-9.2LIBS += -lvtkIOCore-9.2LIBS += -lvtkIOXML-9.2

运行结果:

五、常见问题解决

1. OpenGL上下文问题

如果遇到OpenGL相关错误,确保正确设置了OpenGL格式:

QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());

2. 窗口大小变化问题

当QT窗口大小变化时,可能需要手动更新VTK渲染窗口:

void resizeEvent(QResizeEvent* event) override { QVTKOpenGLNativeWidget::resizeEvent(event); vtkWidget->renderWindow()->Render();}

3. 交互问题

确保启用了交互器:

vtkNew interactor;interactor->SetRenderWindow(vtkWidget->renderWindow());

4. 内存泄漏

  • VTK使用引用计数,通常不需要手动删除对象

  • 对于VTK与QT混合的对象,确保正确管理所有权

5. 渲染问题 

  • 如果出现黑屏,检查渲染器是否添加到渲染窗口

  • 确保调用了ResetCamera()或设置了合适的相机位置

6.高DPI显示支持

启用QT的高DPI缩放

QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

六、高级用法

1. 多视图布局

// 创建多个QVTKOpenGLNativeWidgetQVTKOpenGLNativeWidget* vtkWidget1 = new QVTKOpenGLNativeWidget;QVTKOpenGLNativeWidget* vtkWidget2 = new QVTKOpenGLNativeWidget;// 创建不同的渲染器和场景// ...// 添加到布局QHBoxLayout* layout = new QHBoxLayout;layout->addWidget(vtkWidget1);layout->addWidget(vtkWidget2);QWidget* centralWidget = new QWidget;centralWidget->setLayout(layout);mainWindow.setCentralWidget(centralWidget);

2. 信号与槽连接

// 连接VTK事件到QT槽QObject::connect(vtkWidget, &QVTKOpenGLNativeWidget::mouseEvent, [](QMouseEvent* event) { // 处理鼠标事件 });
// 连接VTK交互事件到QT槽class MyInteractorStyle : public vtkInteractorStyleTrackballCamera {public: static MyInteractorStyle* New(); vtkTypeMacro(MyInteractorStyle, vtkInteractorStyleTrackballCamera); void OnLeftButtonDown() override { // VTK交互代码 emit clicked(); } Q_SIGNALS: void clicked();};// 在QT中连接MyInteractorStyle* style = MyInteractorStyle::New();widget->interactor()->SetInteractorStyle(style);QObject::connect(style, &MyInteractorStyle::clicked, [](){ qDebug() << \"VTK view clicked\";});

 

七、注意事项

  1. 确保VTK和QT版本兼容

  2. 在Windows上可能需要设置平台插件路径

  3. 对于复杂场景,考虑使用vtkGenericOpenGLRenderWindow

  4. 调试时注意OpenGL版本和显卡驱动兼容性