Qt中添加VTK窗口显示点云
Qt中添加VTK窗口并显示点云
我使用的版本是:
VS2019 + QT5.15.2 + VTK9.1
1. 在Qt中添加显示点云的控件
关于添加显示点云控件主要参考了以下链接:salute 链接
1.1 在designer中添加VTK窗口
添加完成之后注意在.sln项目中配置VTK库,否则无法#include <QVTKOpenGLNativeWidget.h>
方法的核心就是将QWidget提升为自定义控件。
QVTKOpenGLNativeWidget 实际上是VTK给写好的一个自定义控件,继承自QWidget类,所以只需要将QWdiget类提升为QVTKOpenGLNativeWidget类就行了
1.用Designer打开项目的界面文件(.ui后缀文件)
2.在左边的控件栏中,将Containers下的“Widget”这个控件拖入到用户界面中,然后右边的对象查看器中就能查到你拖入的QWidget控件对象。
3.对该对象点右键,选择“提升为”,提升为可以理解是将QT自带的控件类提升为开发者编写的自定义控件类。而QVTKOpenGLNativeWidget就是VTK编写的自定义控件类。
4.然后提升的类名称填上“QVTKOpenGLNativeWidget”,头文件填写“QVTKOpenGLNativeWidget.h”。基类选择QWidget。然后点击“添加”-》“提升”
提升的类名称: 指自定义控件的类名称,VTK提供的自定义类名称就是QVTKOpenGLNativeWidget。
头文件: 指自定义控件的头文件,VTK提供的自定义控件类的头文件就是QVTKOpenGLNativeWidget.h。注意大小写。如果不对应的话,会失效。
基类名称: 指自定义的控件类的基类是谁,QVTKOpenGLNativeWidget的基类就是QWidget。选错了也是不行的。
添加: 指保存这个设定,下次可以直接拿来使用,不用重新输入以上信息。
提升: 指将你拖入UI中的QWidget控件,变成你写好的自定义控件类,在这里就是将QWidget类变成QVTKOpenGLNativeWidget类。
5.重命名该窗口控件的对象名,用来写代码的时候识别。网上所见通常命名为“qvtkWidget”
6.最后在你的主窗口类下调用ui的成员变量可以成功呼出qvtkWidget这个vtk窗口控件。
1.2 直接以代码形式添加vtk窗口
这是最简单的方法了,不要用到.ui文件,不需要用到Designer,直接在代码上用。都不需要提升类,直接包含头文件后拿来用就行。
在MainWindow的构造函数中写代码:(不需要照抄,理解以下几行代码在干嘛即可)
//初始化VTK窗口,命名为qvtkWidget(原理和QPushButton这种QT自带的控件一样,只是该控件由VTK提供,用法跟QPushButton是一样的)
QVTKOpenGLNativeWidget* qvtkWidget = new QVTKOpenGLNativeWidget();
//初始化VTK的渲染器,平时用的比较多是vtkRenderWindow,但是在QT中要改用vtkGenericOpenGLRenderWindow,实质上与vtkRenderWindow功能一致
vtkGenericOpenGLRenderWindow* renderWindow = vtkGenericOpenGLRenderWindow()::New();
//将渲染器加入到VTK窗口中。可以先写这一行,后续再将准备好的vtkRenderer加入到renderWindow中也是可以同步数据的
qvtkWidget->setRenderWindow(renderWindow);
//创建网格布局,只是为了方便布局,实际上可以直接调用qvtkwidget的baseSize函数指定窗口大小也行
QGridLayout* displayGrid = new QGridLayout(this);
displayGrid->addWidget(qvtkWidget);
this->setLayout(displayGrid);
需要在MainWindow头文件中包含vtkGenericOpenGLRenderWindow.h和QVTKOpenGLNativeWidget.h头文件。
理解上面的代码,自己在MainWindow构造函数中去使用(在其他地方用也没问题,用法一样)
2. 在添加好的控件上显示点云
在添加的控件上显示点云主要参考此链接:salute链接
2.1 代码
//----------------------------qvtkWidget的初始化-----------------------------------
auto renderer = vtkSmartPointer<vtkRenderer>::New();
auto renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
renderWindow->AddRenderer(renderer);
viewer.reset(new pcl::visualization::PCLVisualizer(renderer, renderWindow, "viewer", false));
ui->qvtkWidget->setRenderWindow(viewer->getRenderWindow()); //此处qvtkWidget是我这个窗口的名称,自定义的
viewer->setupInteractor(ui->qvtkWidget->interactor(), ui->qvtkWidget->renderWindow());
//----------------------------qvtkWidget的初始化-----------------------------------
//----------------------------初始化点云并显示-------------------------------------
//初始化一个点云
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
//加载点云文件
if (pcl::io::loadPCDFile("data/ceshi.pcd", *cloud) == -1)
{
std::cout << "打开文件失败" << std::endl;
}
//刷新显示窗口
ui->qvtkWidget->repaint();
//添加点云
viewer->addPointCloud(cloud, "cloud");
//刷新
ui->qvtkWidget->update();
//视角
viewer->resetCamera();
//----------------------------初始化点云并显示-------------------------------------
3. QVTKOpenGLNativeWidget.h
的解释
原链接请参考QVTKOpenGLNativeWidget.h
源文件
3.1 类QVTKOpenGLNativeWidget的简介:
QVTKOpenGLNativeWidget是QOpenGLWidget的子类,用于在Qt应用程序中承载一个vtkGenericOpenGLRenderWindow。
请注意,QVTKOpenGLNativeWidget只能与vtkGenericOpenGLRenderWindow一起使用。
这是因为QOpenGLWidget希望接管窗口管理和OpenGL上下文的创建。
使用vtkXRenderWindow或vtkWin32RenderWindow(以及其他特定于平台的vtkRenderWindow子类)进行可靠工作非常棘手且充满问题。
由于QVTKOpenGLNativeWidget使用QOpenGLWidget来创建OpenGL上下文,
它使用QSurfaceFormat(使用QOpenGLWidget::setFormat或QSurfaceFormat::setDefaultFormat进行设置)来创建适当的窗口和上下文。
您可以使用QVTKOpenGLNativeWidget::copyToFormat获取适用于vtkRenderWindow的QSurfaceFormat。
QVTKOpenGLNativeWidget的典型用法如下:
// 在初始化QApplication之前,设置默认的表面格式。
QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());
vtkNew<vtkGenericOpenGLRenderWindow> window;
QPointer<QVTKOpenGLNativeWidget> widget = new QVTKOpenGLNativeWidget(...);
widget->SetRenderWindow(window.Get());
// 如果使用任何标准视图例如vtkContextView,则可以执行以下操作。
vtkNew<vtkContextView> view;
view->SetRenderWindow(window.Get());
// 您可以继续使用`window`作为常规vtkRenderWindow,包括添加渲染器、演员等。
3.2 OpenGL上下文:
在QOpenGLWidget(QVTKOpenGLNativeWidget的父类)中,所有渲染都发生在帧缓冲对象中。因此,在渲染代码中必须小心,永远不要直接重新绑定默认帧缓冲,即ID为0。
QVTKOpenGLNativeWidget创建了一个内部的QOpenGLFramebufferObject,独立于父类创建的QOpenGLFramebufferObject,用于vtkRenderWindow进行渲染。
这种显式的双缓冲在避免VTK中仅在临时后备缓冲区上进行的渲染时(例如进行选择时)破坏在屏幕上组合的结果时非常有用。
3.3 处理渲染和绘制:
QWidget子类(包括QOpenGLWidget和QVTKOpenGLNativeWidget)在QWidget::paint中显示其内容,以响应绘制事件。
QOpenGLWidget子类应在QOpenGLWidget::paintGL中进行OpenGL渲染。
QWidget可能由于各种原因接收到绘制事件,包括小部件获得焦点/失去焦点,UI中的其他小部件(例如状态栏中的QProgressBar)的更新等。
在VTK应用程序中,每当vtkRenderWindow需要更新以进行新的渲染时,可以通过在其上调用vtkRenderWindow::Render来完成。
设置在渲染窗口上的vtkRenderWindowInteractor确保随着对影响渲染结果的交互发生,它会调用渲染窗口上的Render。
由于Qt中的paint可能被调用得比需要的频繁,我们避免了每次发生这种情况时可能昂贵的vtkRenderWindow::Render调用。相反,QVTKOpenGLNativeWidget依赖于VTK应用程序在需要更新渲染时在渲染窗口上调用vtkRenderWindow::Render。
paintGL只是将由最近一次渲染调用vtkRenderWindow::Render渲染的结果传递给Qt窗口系统以在屏幕上组合。
在某些情况下,可能仍然需要在paint中进行渲染,例如如果窗口的大小被调整或Qt必须重新创建OpenGL上下文。
在这些情况下,QVTKOpenGLNativeWidget::paintGL可以通过调用QVTKOpenGLNativeWidget::renderVTK请求进行渲染。
3.4 注意事项:
QVTKOpenGLNativeWidget不支持立体声,请使用QVTKOpenGLStereoWidget以获取立体声渲染支持。
QVTKOpenGLNativeWidget针对Qt版本5.5及以上版本进行了优化。
参考:QVTKOpenGLStereoWidget QVTKRenderWidget
4. VTK文档及使用例程
VTK总文档入口
VTK的C++接口文档
VTK的c++使用例程
遇到的问题
在配好PCL库和VTK库的前提下,直接构建工程并运行,会产生以下报错:
配置VTK动态链接库到系统环境变量之后,仍然报此类错误,exe文件无法加载到此dll动态链接。
只有把vtkGUISupportQt-9.1.dll
放在exe同级目录才有效。暂时没找到原因。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!