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\";});
七、注意事项
-
确保VTK和QT版本兼容
-
在Windows上可能需要设置平台插件路径
-
对于复杂场景,考虑使用vtkGenericOpenGLRenderWindow
-
调试时注意OpenGL版本和显卡驱动兼容性


