3D Slicer光标设置流程

本文详细解析了在3DSlicer中如何设置光标,包括通过displaymanager和直调的方式,以及如何禁用内置的更新机制来实现自定义光标,以vtkMRMLCrosshairDisplayableManager为例提供了具体实现代码。
摘要由CSDN通过智能技术生成


前言

在基于3D Slicer的医学影像项目中可能涉及到自定义光标的情况 ,这里给出slicer光标设置流程分析,并提供一种实现自定义光标的方法。


一、slicer光标设置流程分析

slicer是基于QT和VTK的,其光标设置也是如此,实际上使用的是VTK和QT的结合。
其光标设置流程包括两种模式:

  1. 通过display manager
    在这里插入图片描述

  2. 通过sliceview直调
    在这里插入图片描述
    在这里插入图片描述
    需要注意的是:通过display manager 实现的途径中都是使用vtk cursor值,比如VTK_CURSOR_ARROW,VTK_CURSOR_DEFAULT,VTK_CURSOR_CUSTOM,只在最后设置到QWidget时才将其转换为 Qt::ArrowCursor这样的qt光标对象,转换函数为QVTKRenderWindowAdapter::QVTKInternals::setCursor(int vtk_cursor)。
    而直调方式则是直接设置QCursor到QWidget中。

此外,由于slicer的qSlicerMouseModeToolBarPrivate::updateCursor()会根据当前action不同以及vtkMRMLInteractionNode模式不同,动态设置光标,会将直接通过窗口设置的光标覆盖。

二、自定义光标

实现自定义光标,需要首先把slicer自己的qSlicerMouseModeToolBarPrivate::updateCursor禁用,防止其修改光标。然后再按照display manager设置光标的流程设置光标。
以vtkMRMLCrosshairDisplayableManager类为例,这里给出的方式是
给displaymanager添加设置光标的回调函数:

void SetMouseCursor(int cursor) override;
typedef std::function<int(vtkMRMLNode* viewnode, int widgetstate,int cursor)> CustomCursorCallback;
CustomCursorCallback customcursorCallback;
void SetCustomCursorCallback(CustomCursorCallback callback);

重写SetMouseCursor,由其调用回调函数:

void vtkMRMLCrosshairDisplayableManager::SetMouseCursor(int cursor) {
    this->Superclass::SetMouseCursor(cursor);//must call first let renderwindow record the cursor
    int done = 0;
    if (customcursorCallback && this->Internal->SliceIntersectionWidget) {
        done = customcursorCallback(this->GetMRMLDisplayableNode(), this->Internal->SliceIntersectionWidget->GetWidgetState(),cursor);
    }
    if(done == 0) {
        this->Superclass::SetMouseCursor(cursor);
    }
}

回调函数负责将vtk cursor值转为所需光标,并设置给对应的sliceview窗口,示例如下:

int vtkSlicerEditorLogic::CustomCursorCallbackForCrosshair(vtkMRMLNode* viewnode, int widgetstate, int cursor) {
    QCursor qcursor;
    if (cursor == VTK_CURSOR_CUSTOM) {
        QIcon icon(":/Icons/custom.png");
        qcursor = QCursor(icon.pixmap(icon.actualSize(QSize(24, 24))));
    }
    else if (cursor == VTK_CURSOR_ARROW) {
        QIcon icon(":/Icons/arrow.png");
        qcursor = QCursor(icon.pixmap(icon.actualSize(QSize(24, 24))));
    }
    else {
        return 0;
    }
    qSlicerLayoutManager* layoutManager = GetApplication()->layoutManager();
    if (layoutManager) {
        QWidget* viewwidget = layoutManager->viewWidget(viewnode);
        qMRMLSliceWidget* slicewidget = dynamic_cast<qMRMLSliceWidget*>(viewwidget);
        if (slicewidget) {
            slicewidget->sliceView()->setViewCursor(qcursor);
        }
        return 1;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值