首先,让我们创建 `VTKWidget.h` 文件:
```
#ifndef VTKWIDGET_H
#define VTKWIDGET_H
#include <QWidget>
#include <QVTKOpenGLNativeWidget.h>
#include <vtkSmartPointer.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkActor.h>
class VTKWidget : public QWidget
{
Q_OBJECT
public:
explicit VTKWidget(QWidget* parent = nullptr);
private slots:
void toggleShape();
private:
void createSphere();
void createCone();
QVTKOpenGLNativeWidget* vtkWidget;
vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow;
vtkSmartPointer<vtkRenderer> renderer;
vtkSmartPointer<vtkActor> actor;
};
#endif // VTKWIDGET_H
```
然后,创建 `VTKWidget.cpp` 文件:
```
#include "VTKWidget.h"
#include <QPushButton>
#include <QVBoxLayout>
#include <vtkSphereSource.h>
#include <vtkConeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkAutoInit.h>
// 初始化所需的 VTK 渲染模块
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTKWidget::VTKWidget(QWidget* parent) : QWidget(parent)
{
// 创建VTK渲染窗口和渲染器
renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
renderer = vtkSmartPointer<vtkRenderer>::New();
renderWindow->AddRenderer(renderer);
// 创建QVTKOpenGLNativeWidget并设置渲染窗口
vtkWidget = new QVTKOpenGLNativeWidget(this);
vtkWidget->setRenderWindow(renderWindow);
// 创建球体
createSphere();
// 创建按钮来切换显示的形状
QPushButton* toggleButton = new QPushButton("Toggle Shape", this);
connect(toggleButton, &QPushButton::clicked, this, &VTKWidget::toggleShape);
// 设置布局
QVBoxLayout* layout = new QVBoxLayout(this);
layout->addWidget(vtkWidget);
layout->addWidget(toggleButton);
setLayout(layout);
}
void VTKWidget::createSphere()
{
vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New();
sphereSource->SetCenter(0.0, 0.0, 0.0);
sphereSource->SetRadius(0.5);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(sphereSource->GetOutputPort());
actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
renderer->AddActor(actor);
renderer->ResetCamera();
}
void VTKWidget::createCone()
{
vtkSmartPointer<vtkConeSource> coneSource = vtkSmartPointer<vtkConeSource>::New();
coneSource->SetHeight(1.0);
coneSource->SetRadius(0.5);
coneSource->SetResolution(100);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(coneSource->GetOutputPort());
actor->SetMapper(mapper);
renderer->ResetCamera();
}
void VTKWidget::toggleShape()
{
static bool isSphere = true;
if (isSphere)
{
createCone();
}
else
{
createSphere();
}
isSphere = !isSphere;
vtkWidget->update();
}
```
最后,我们需要更新 `main.cpp` 文件:
```
#include <QApplication>
#include <QMainWindow>
#include "VTKWidget.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow mainWindow;
VTKWidget* vtkWidget = new VTKWidget(&mainWindow);
mainWindow.setCentralWidget(vtkWidget);
mainWindow.resize(800, 600);
mainWindow.show();
return app.exec();
}
```
这种分离可以带来以下好处:
1. 提高代码的可读性:将接口和实现分开,使得代码结构更清晰。
2. 提高编译效率:当只修改实现时,只需要重新编译 .cpp 文件。
3. 封装性:可以在头文件中只暴露公共接口,将私有实现细节隐藏在 .cpp 文件中。
记得更新您的 CMakeLists.txt 文件,包含新的源文件:
```
cmake_minimum_required(VERSION 3.12)
project(QtVtkWidgetExample)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
find_package(Qt5 COMPONENTS Widgets REQUIRED)
find_package(VTK COMPONENTS
vtkCommonCore
vtkFiltersSources
vtkInteractionStyle
vtkRenderingOpenGL2
vtkGUISupportQt
REQUIRED
)
include(${VTK_USE_FILE})
add_executable(QtVtkWidgetExample
main.cpp
VTKWidget.cpp
VTKWidget.h
)
target_link_libraries(QtVtkWidgetExample PRIVATE Qt5::Widgets ${VTK_LIBRARIES})
```
这样,您的程序就被很好地组织成了多个文件,提高了代码的可维护性和可读性。如果您有任何问题或需要进一步的解释,请随时告诉我。