How to Activate Slice View on Mouse Hover

Hi everyone,

I’ve set up multiple shortcuts for each view, but they only work if I click to activate the view first. I’d like to improve my workflow by activating views on mouse hover instead, so shortcuts are immediately available without extra clicks.

Is there a way to enable view activation on hover?

Generally the views act like other widgets, like text entry, with a click-to-focus model. You can listen for window enter events and force the focus to change, but on some OSs in the past we found this also raised the application window if you moved the mouse through the view even if there was another application in front, which was annoying to users. Maybe you can find a way to have focus follow the mouse only if the Slicer application is in the foreground.

If, for example I’m in paint mode, what I do is use the space bar to toggle to the arrow cursor, then click in the view, then space bar again so that keyboard and mouse events to to the view of choice.

1 Like

Thanks for your response; this is very insightful!

I’ve created a FocusOnHover class to set focus when the mouse enters or leaves the view. The print("enter") and print("leave") statements work as expected, but setFocus doesn’t seem to activate the view, and vtk shortcuts still aren’t working.

Here’s the code I’m using:

import qt

class FocusOnHover(qt.QObject):
    def __init__(self, widget):
        super().__init__()
        self.widget = widget
        # Install event filter
        self.widget.installEventFilter(self)

    def eventFilter(self, obj, event):
        # Check event type
        if obj == self.widget:
            if event.type() == qt.QEvent.Enter:
                # Set focus when mouse enters
                print("enter")
                self.widget.setFocus(qt.Qt.MouseFocusReason)
            elif event.type() == qt.QEvent.Leave:
                # Clear focus when mouse leaves
                print("leave")
                self.widget.clearFocus()
        return False

layoutManager = slicer.app.layoutManager()
threeDView = layoutManager.threeDWidget(0).threeDView()  # Select specific 3D view
hover_focus = FocusOnHover(threeDView)

I don’t recall, but you may need to do something at the VTK render window or render window interactor level too.


class FocusOnHover(qt.QObject):
    def __init__(self, threeDWidget):
        super().__init__()
        self.threeDWidget = threeDWidget
        self.threeDWidget.installEventFilter(self)

    def eventFilter(self, obj, event):
        if obj == self.threeDWidget:
            threeDView = self.threeDWidget.threeDView()
            renderWindow = threeDView.renderWindow()
            interactor = renderWindow.GetInteractor()

            if event.type() == qt.QEvent.Enter:
                print("enter")
                self.threeDWidget.setFocus(qt.Qt.MouseFocusReason)
                interactor.Enable()
                slicer.app.processEvents()
                
            elif event.type() == qt.QEvent.Leave:
                # 鼠标离开时禁用交互器
                print("leave")
                interactor.Disable()
                self.threeDWidget.clearFocus()
                
        return False

layoutManager = slicer.app.layoutManager()
threeDWidget = layoutManager.threeDWidget(0) 
hover_focus = FocusOnHover(threeDWidget)``` the VTK interactor doesn’t seem to activate when I call `interactor.Enable()`. this make me confused, it's seems can't make it active programmatically