#ifndef NMWXVTKRENDERCONTAINERWIDGET_H #define NMWXVTKRENDERCONTAINERWIDGET_H #include "nmRender_global.h" #include "nmVTKViewCommandController.h" #include #include class QLabel; class QEvent; class QMenu; class QStackedWidget; class QVBoxLayout; class QVTKWidget; class nmVTKCameraController; class nmVTKImageExporter; class nmVTKInteractionManager; class nmVTKOrientationMarkerController; class nmVTKRotationCenterMarkerLayer; class nmVTKRotationCenterPicker; class nmVTKScene; class vtkProp; class vtkRenderer; class vtkRenderWindow; class vtkRenderWindowInteractor; class vtkInteractorStyle; /** * @brief 可组合的 Qt + VTK 通用渲染容器。 * * 容器独占 Renderer、业务 Scene、系统 Scene、相机、交互、方向轴和旋转 * 中心拾取服务,但不创建任何业务 Actor。调用方通过公开的业务 Scene 组织 * 图层;系统 Scene 仅管理容器内部装饰,业务清场不会删除它们。 */ class NM_RENDER_EXPORT nmWxVTKRenderContainerWidget : public QWidget { Q_OBJECT public: /** @brief 创建独立的 VTK 显示外壳,并初始化场景、相机、交互和方向轴服务。 */ explicit nmWxVTKRenderContainerWidget(QWidget* pParent = nullptr); /** @brief 按命令、拾取、方向轴、交互、图层、相机和 Renderer 顺序解除资源。 */ virtual ~nmWxVTKRenderContainerWidget(); /** @brief 返回 Qt 承载控件;调用方不得删除或重新设置父对象。 */ QVTKWidget* getVtkWidget() const; /** @brief 返回当前容器独占的 Renderer 非所有权指针。 */ vtkRenderer* getRenderer() const; /** @brief 返回 QVTKWidget 持有的 RenderWindow 非所有权指针。 */ vtkRenderWindow* getRenderWindow() const; /** * @brief 返回 RenderWindow 的 Interactor 非所有权指针。 * @warning 不得直接替换其 InteractorStyle,应使用容器的交互模式接口。 */ vtkRenderWindowInteractor* getInteractor() const; /** @brief 返回业务 Scene;clear() 不影响容器内部系统图层。 */ nmVTKScene* getScene() const; /** @brief 返回当前容器独占的通用命令控制器非所有权指针。 */ nmVTKViewCommandController* getViewCommandController() const; /** @brief 返回当前容器独占的方向轴控制器非所有权指针。 */ nmVTKOrientationMarkerController* getOrientationMarkerController() const; /** @brief 设置工具栏和右键菜单可使用的通用命令集合。 */ void setViewCommandCapabilities( nmVTKViewCommandController::ViewCommands eCommands); /** @brief 注册唯一可拾取几何;传入 nullptr 会取消模式并隐藏中心标记。 */ void setRotationCenterPickTarget(vtkProp* pTarget); /** @brief 返回当前是否正在等待用户选择旋转中心。 */ bool isRotationCenterPicking() const; /** @brief 隐藏旋转中心标记,不修改独立中心或相机且不主动渲染。 */ void hideRotationCenterMarker(); /** @brief 安装临时交互样式,并由容器保持其 VTK 引用。 */ bool installInteractionStyle(vtkInteractorStyle* pStyle); /** @brief 将 Interactor 恢复为当前容器独占的默认相机交互样式。 */ bool restoreDefaultInteraction(); /** @brief 清除活动交互模式,但保留容器对 Interactor 的绑定。 */ void clearInteractionStyle(); /** @brief 提交一次渲染;无有效 RenderWindow 时安全返回。 */ void renderView(); /** * @brief 沿 +Z 方向设置正交顶视图并适配当前可见边界,但不立即渲染。 * * 供业务层批量替换几何时使用,调用方应在整批更新结束后统一 renderView。 */ bool fitTopViewWithoutRender(); /** @brief 将独立旋转中心设为可见边界中心,但不修改画面或立即渲染。 */ bool resetRotationCenterWithoutRender(); /** @brief 切换到 VTK 页面并提交一次渲染。 */ void showReadyState(); /** @brief 显示无数据状态,消息由业务调用方提供。 */ void showEmptyState(const QString& sMessage); /** @brief 显示错误状态,消息由业务调用方提供。 */ void showErrorState(const QString& sMessage); /** @brief 显示渲染中状态,消息由业务调用方提供。 */ void showRenderingState(const QString& sMessage); signals: /** * @brief 在公共菜单构造期间同步发出,供调用方追加临时 QAction。 * @warning 接收方不得保存 pMenu;信号返回后菜单即由容器继续管理。 */ void contextMenuAboutToShow(QMenu* pMenu); /** @brief 将容器确认后的拾取状态同步给公共 QAction。 */ void rotationCenterPickingChanged(bool bPicking); public slots: /** @brief 按固定倍率 1.2 放大,成功后统一渲染一次。 */ void zoomIn(); /** @brief 按固定倍率 1.0 / 1.2 缩小。 */ void zoomOut(); /** @brief 保持观察方向和投影方式,仅适配当前可见边界。 */ void fitView(); /** @brief 恢复透视投影,并按当前可见 Prop 的边界适配相机。 */ void resetCamera(); /** @brief 沿 +Z 方向设置正交顶视图。 */ void setTopView(); /** @brief 沿 -Y 方向设置正交前视图。 */ void setFrontView(); /** @brief 沿 +X 方向设置正交右视图。 */ void setRightView(); /** @brief 设置透视等轴视图。 */ void setIsometricView(); /** @brief 设置独立世界坐标旋转中心,不移动当前画面。 */ void setRotationCenter(double dX, double dY, double dZ); /** @brief 将旋转中心恢复为当前可见边界中心,不移动当前画面。 */ void resetRotationCenter(); /** @brief 请求开始或取消一次性旋转中心拾取模式。 */ void setRotationCenterPickingEnabled(bool bEnabled); protected: /** @brief 优先处理拾取事件,再处理 QVTKWidget 的右键菜单。 */ virtual bool eventFilter(QObject* pObject, QEvent* pEvent); private slots: /** @brief 焦点切换完成后取消仍处于活动或待消费释放状态的拾取。 */ void cancelRotationCenterPickingAfterFocusOut(); /** @brief 弹出文件对话框并保存当前 RenderWindow 图像。 */ void saveImage(); /** @brief 将当前 RenderWindow 图像复制到系统剪贴板。 */ void copyImage(); /** @brief 打开系统打印对话框并输出当前图像。 */ void printImage(); /** @brief 打开打印预览对话框。 */ void printPreview(); private: Q_DISABLE_COPY(nmWxVTKRenderContainerWidget) enum ViewState { ViewState_Ready = 0, ///< 显示 VTK 渲染页面。 ViewState_Empty, ///< 显示无数据提示页面。 ViewState_Error, ///< 显示错误提示页面。 ViewState_Rendering ///< 显示渲染中提示页面。 }; /** @brief 统一设置非就绪状态的文字、颜色和当前页面。 */ void showMessageState(ViewState eState, const QString& sMessage); /** @brief 修改独立中心和可选标记但不渲染,由外层统一提交画面。 */ bool applyRotationCenter(double dX, double dY, double dZ, bool bShowMarker); /** * @brief 将逻辑中心和 Marker 同步到可见边界中心,但不主动渲染。 * @return 逻辑中心更新成功时返回 true;Marker 同步失败会隐藏标记。 */ bool resetRotationCenterStateWithoutRender(); /** @brief 取消模式、恢复光标并同步 QAction,不修改既有中心标记。 */ void cancelRotationCenterPicking(); /** @brief 处理一次拾取事件;返回 true 表示事件必须停止向 VTK 传播。 */ bool handleRotationCenterPickEvent(QEvent* pEvent); /** @brief 仅同步 Marker 世界几何,不主动渲染。 */ void synchronizeRotationCenterMarker(); /** @brief Ready、能力、主目标及独立中心均有效时显示标记。 */ void updateRotationCenterMarkerVisibility(); /** @brief 按目标、Marker 和当前交互样式同步命令的额外可用条件。 */ void updateRotationCenterCommandAvailability(); /** @brief 通过系统 Scene 稳定 ID 校验 Marker Layer 非所有权指针。 */ nmVTKRotationCenterMarkerLayer* getRotationCenterMarkerLayer() const; /** @brief 判断调用线程是否为 Qt GUI 线程。 */ bool isGuiThread() const; // Qt 对象由父子关系拥有,以下成员只是便于访问的非所有权指针。 QVBoxLayout* m_pMainLayout; QStackedWidget* m_pStateStack; QWidget* m_pStatePage; QLabel* m_pStateLabel; QVTKWidget* m_pVtkWidget; // Renderer 与通用服务均为当前容器实例独占,不与其他视图共享状态。 vtkSmartPointer m_pRenderer; nmVTKScene* m_pScene; ///< 公开给业务控制器的图层集合。 nmVTKScene* m_pSystemScene; ///< 容器私有装饰图层集合,不对外暴露。 nmVTKCameraController* m_pCameraController; nmVTKInteractionManager* m_pInteractionManager; nmVTKImageExporter* m_pImageExporter; nmVTKViewCommandController* m_pViewCommandController; nmVTKOrientationMarkerController* m_pOrientationMarkerController; nmVTKRotationCenterPicker* m_pRotationCenterPicker; ///< 本容器独占。 nmVTKRotationCenterMarkerLayer* m_pRotationCenterMarkerLayer; ///< 系统 Scene 所有。 }; #endif // NMWXVTKRENDERCONTAINERWIDGET_H