VTK|结合qt创建通用按钮控制显隐(边框、坐标轴、点线面)
文章目录
- 增加边框BoundingBox
- 添加addBoundingBox
- 添加BoundingBox控制按钮
- 点击按钮之后的槽函数
- 添加坐标轴
- 增加点线面显隐控制按钮
- 添加控制点线面显隐的按钮到三维显示界面
- 控制面显示槽函数
- 控制线显示槽函数
- 控制点显示槽函数
增加边框BoundingBox
增加边框BoundingBox并通过按钮控制显隐
需要的全局变量
// 显示场景QVTKOpenGLWidget *m_pScene;vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow_;vtkSmartPointer<vtkRenderer> renderer_;// 边框显示vtkSmartPointer<vtkActor> boundingBoxActor_; // 用于存储BoundingBox的Actorbool isBoundingBoxVisible_; // 控制BoundingBox的显隐状态vtkSmartPointer<vtkTextActor> boundingBoxButtonActor_;
添加addBoundingBox
void ThreeDimensionalDisplayPage::addBoundingBox(vtkSmartPointer<vtkPolyData> polyData)
{if (boundingBoxActor_){renderer_->RemoveActor(boundingBoxActor_);boundingBoxActor_ = nullptr;}vtkNew<vtkOutlineFilter> outlineFilter;outlineFilter->SetInputData(polyData);outlineFilter->Update();vtkNew<vtkPolyDataMapper> outlineMapper;outlineMapper->SetInputConnection(outlineFilter->GetOutputPort());boundingBoxActor_ = vtkSmartPointer<vtkActor>::New();boundingBoxActor_->SetMapper(outlineMapper);boundingBoxActor_->GetProperty()->SetColor(1.0, 0.0, 0.0);boundingBoxActor_->GetProperty()->SetLineWidth(2.0);boundingBoxActor_->SetVisibility(isBoundingBoxVisible_); // 根据状态决定是否显示renderer_->AddActor(boundingBoxActor_);
}
添加BoundingBox控制按钮
void ThreeDimensionalDisplayPage::addBoundingBoxControlButton()
{// 避免重复添加if (boundingBoxButtonActor_ && renderer_->HasViewProp(boundingBoxButtonActor_))return;vtkNew<vtkTextActor> textActor;textActor->SetInput("Hide Bounding Box");vtkTextProperty *textProp = textActor->GetTextProperty();textProp->SetFontSize(24);textProp->SetColor(0.0, 0.0, 0.0); // 黑色文字textProp->SetBackgroundColor(0.8, 0.8, 0.8); // 灰色背景textProp->SetBackgroundOpacity(1.0);textProp->SetFrame(1);textProp->SetFrameColor(0.0, 0.0, 0.0);textActor->SetDisplayPosition(10, 10);renderer_->AddActor2D(textActor);boundingBoxButtonActor_ = textActor;// 注册鼠标点击事件(只注册一次)static bool observerAdded = false;if (!observerAdded){vtkNew<vtkCallbackCommand> clickCallback;clickCallback->SetClientData(this);clickCallback->SetCallback([](vtkObject *caller, unsigned long, void *clientData, void *){auto *self = static_cast<ThreeDimensionalDisplayPage *>(clientData);int *clickPos = static_cast<vtkRenderWindowInteractor *>(caller)->GetEventPosition();int x = clickPos[0];int y = clickPos[1];// 判断是否点击在按钮上(近似判断)int *pos = self->boundingBoxButtonActor_->GetPositionCoordinate()->GetComputedDisplayValue(self->renderer_);int btnX = pos[0];int btnY = pos[1];int width = 220, height = 40;if (x >= btnX && x <= btnX + width &&y >= btnY && y <= btnY + height){self->OnBoundingBoxButtonClicked();} });interactor_->AddObserver(vtkCommand::LeftButtonPressEvent, clickCallback);observerAdded = true;}isBoundingBoxVisible_ = true;
}
点击按钮之后的槽函数
void ThreeDimensionalDisplayPage::OnBoundingBoxButtonClicked()
{if (!boundingBoxActor_)return;isBoundingBoxVisible_ = !isBoundingBoxVisible_;boundingBoxActor_->SetVisibility(isBoundingBoxVisible_);if (boundingBoxButtonActor_){boundingBoxButtonActor_->SetInput(isBoundingBoxVisible_ ? "Hide Bounding Box" : "Show Bounding Box");}renderWindow_->Render();
}
添加坐标轴
需要的全局变量,防止重复创建
// 坐标轴显示vtkSmartPointer<vtkAxesActor> axes_;vtkSmartPointer<vtkOrientationMarkerWidget> marker_;
创建坐标轴
void ThreeDimensionalDisplayPage::addCoordinateAxes()
{if (!axes_)axes_ = vtkSmartPointer<vtkAxesActor>::New();axes_->SetTotalLength(10.0, 10.0, 10.0);if (!marker_)marker_ = vtkSmartPointer<vtkOrientationMarkerWidget>::New();marker_->SetOrientationMarker(axes_);marker_->SetOutlineColor(0.9300, 0.5700, 0.1300);marker_->SetInteractor(m_pScene->GetInteractor());marker_->SetDefaultRenderer(renderer_);marker_->SetViewport(0.8, 0.0, 1.0, 0.2);marker_->SetEnabled(1);marker_->InteractiveOn();
}
增加点线面显隐控制按钮
需要的全局变量,防止重复创建
// 添加控制点线面显隐的按钮到三维显示界面void addObjVisibilityControlButtons();// 控制面显示槽函数void toggleSurfaceVisibility();// 控制线显示槽函数void toggleWireframeVisibility();// 控制点显示槽函数void togglePointsVisibility();// 控制obj点线面的显隐vtkSmartPointer<vtkActor> surfaceActor_;vtkSmartPointer<vtkActor> wireframeActor_;vtkSmartPointer<vtkActor> pointsActor_;// 控制obj点线面显隐的按钮vtkSmartPointer<vtkTextActor> surfaceToggleButton_;vtkSmartPointer<vtkTextActor> wireframeToggleButton_;vtkSmartPointer<vtkTextActor> pointsToggleButton_;
添加控制点线面显隐的按钮到三维显示界面
void ThreeDimensionalDisplayPage::addObjVisibilityControlButtons()
{// 如果已经创建过按钮,则直接重新添加到 renderer_if (surfaceToggleButton_){surfaceToggleButton_->SetInput("Hide Surface");wireframeToggleButton_->SetInput("Hide Wireframe");pointsToggleButton_->SetInput("Hide Points");renderer_->AddActor2D(surfaceToggleButton_);renderer_->AddActor2D(wireframeToggleButton_);renderer_->AddActor2D(pointsToggleButton_);return;}// 按钮文字及初始状态std::vector<std::pair<std::string, vtkSmartPointer<vtkTextActor> *>> buttons = {{"Hide Surface", &surfaceToggleButton_},{"Hide Wireframe", &wireframeToggleButton_},{"Hide Points", &pointsToggleButton_}};int startY = 60; // 初始 Y 位置for (auto &[text, actorPtr] : buttons){auto textActor = vtkSmartPointer<vtkTextActor>::New();textActor->SetInput(text.c_str());auto *textProp = textActor->GetTextProperty();textProp->SetFontSize(20);textProp->SetColor(0.0, 0.0, 0.0);textProp->SetBackgroundColor(0.9, 0.9, 0.9);textProp->SetBackgroundOpacity(1.0);textProp->SetFrame(1);textProp->SetFrameColor(0.0, 0.0, 0.0);textActor->SetDisplayPosition(10, startY);renderer_->AddActor2D(textActor);*actorPtr = textActor;startY += 50; // 下一个按钮向下偏移}// 注册鼠标事件(只注册一次)static bool observerAdded = false;if (!observerAdded){vtkNew<vtkCallbackCommand> clickCallback;clickCallback->SetClientData(this);clickCallback->SetCallback([](vtkObject *caller, unsigned long, void *clientData, void *){auto* self = static_cast<ThreeDimensionalDisplayPage*>(clientData);int* clickPos = static_cast<vtkRenderWindowInteractor*>(caller)->GetEventPosition();int x = clickPos[0];int y = clickPos[1];std::vector<std::pair<vtkSmartPointer<vtkTextActor>, std::function<void()>>> buttons = {{self->surfaceToggleButton_, [&]() { self->toggleSurfaceVisibility(); }},{self->wireframeToggleButton_, [&]() { self->toggleWireframeVisibility(); }},{self->pointsToggleButton_, [&]() { self->togglePointsVisibility(); }}};for (auto& [actor, func] : buttons){int* pos = actor->GetPositionCoordinate()->GetComputedDisplayValue(self->renderer_);int bx = pos[0];int by = pos[1];int width = 200, height = 40;if (x >= bx && x <= bx + width &&y >= by && y <= by + height){func();break;}} });interactor_->AddObserver(vtkCommand::LeftButtonPressEvent, clickCallback);observerAdded = true;}
}
控制面显示槽函数
void ThreeDimensionalDisplayPage::toggleSurfaceVisibility()
{if (surfaceActor_){bool visible = surfaceActor_->GetVisibility();surfaceActor_->SetVisibility(!visible);if (surfaceToggleButton_)surfaceToggleButton_->SetInput(visible ? "Show Surface" : "Hide Surface");renderWindow_->Render();}
}
控制线显示槽函数
void ThreeDimensionalDisplayPage::toggleWireframeVisibility()
{if (wireframeActor_){bool visible = wireframeActor_->GetVisibility();wireframeActor_->SetVisibility(!visible);if (wireframeToggleButton_)wireframeToggleButton_->SetInput(visible ? "Show Wireframe" : "Hide Wireframe");renderWindow_->Render();}
}
控制点显示槽函数
void ThreeDimensionalDisplayPage::togglePointsVisibility()
{if (pointsActor_){bool visible = pointsActor_->GetVisibility();pointsActor_->SetVisibility(!visible);if (pointsToggleButton_)pointsToggleButton_->SetInput(visible ? "Show Points" : "Hide Points");renderWindow_->Render();}
}
也可以使用qpushbutton进行控制,逻辑更加简单,不需要场景里添加按钮了,创建按钮后直接连接toggleSurfaceVisibility即可。