# how to use left mouse click & drag to browse slice

**URL:** <https://discourse.slicer.org/t/how-to-use-left-mouse-click-drag-to-browse-slice/18945>\
**Category:** Development\
**Tags:** python\
**Created:** [July 27, 2021, 1:39pm UTC](https://discourse.slicer.org/t/how-to-use-left-mouse-click-drag-to-browse-slice/18945 "2021-07-27T13:39:04Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![wycstar](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/wycstar/32/11800_2.png) [@wycstar](https://discourse.slicer.org/u/wycstar)\
**Post date:** [July 27, 2021, 1:39pm UTC](https://discourse.slicer.org/t/how-to-use-left-mouse-click-drag-to-browse-slice/18945/1 "2021-07-27T13:39:04Z")

</div>

NOT use shift, only use left mouse click && drag to browse the slice in each sliceWidge(Red ,green etc) separately

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [July 27, 2021, 4:06pm UTC](https://discourse.slicer.org/t/how-to-use-left-mouse-click-drag-to-browse-slice/18945/2 "2021-07-27T16:06:52Z")

</div>

You can make left-click-and-drag set the slice intersection position by mapping the left-click-and-drag GUI event to “slice translate” widget event:

```python
for viewName in slicer.app.layoutManager().sliceViewNames():
    widget = slicer.app.layoutManager().sliceWidget(viewName).sliceView().displayableManagerByClassName("vtkMRMLCrosshairDisplayableManager").GetSliceIntersectionWidget()
    widget.SetEventTranslationClickAndDrag(widget.WidgetStateIdle, vtk.vtkCommand.LeftButtonPressEvent, vtk.vtkEvent.NoModifier, widget.WidgetStateTranslate, widget.WidgetEventTranslateStart, widget.WidgetEventTranslateEnd)

```

If you want this behavior to be persistent then you can put this code snippet into your startup `.slicerrc.py` file.

---

<div class="post-metadata">

**Author:** ![wycstar](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/wycstar/32/11800_2.png) [@wycstar](https://discourse.slicer.org/u/wycstar)\
**Post date:** [July 28, 2021, 3:03am UTC](https://discourse.slicer.org/t/how-to-use-left-mouse-click-drag-to-browse-slice/18945/3 "2021-07-28T03:03:38Z")

</div>

thx nice lassoan 😀 , but i want to browse the slice in current widge, for example, in red widget i want to browse the slice in it by mouse click and drag

---

<div class="post-metadata">

**Author:** ![jamesobutler](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/jamesobutler/32/7511_2.png) [@jamesobutler](https://discourse.slicer.org/u/jamesobutler)\
**Post date:** [July 28, 2021, 3:47am UTC](https://discourse.slicer.org/t/how-to-use-left-mouse-click-drag-to-browse-slice/18945/4 "2021-07-28T03:47:25Z")

</div>

So you want to browse (change slice offset) for the current widget with left mouse click and drag over the image data? Is there a reason you do not want to left mouse click and drag the slider at the top of the slice widget to change slice offset?

There are other ways to change slice offset of the current widget including:

- mouse scroll wheel while over the slice
- left/right arrow keys
- “f” and “b” keys

Are these inconvenient methods for you?

---

<div class="post-metadata">

**Author:** ![wycstar](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/wycstar/32/11800_2.png) [@wycstar](https://discourse.slicer.org/u/wycstar)\
**Post date:** [July 28, 2021, 3:54am UTC](https://discourse.slicer.org/t/how-to-use-left-mouse-click-drag-to-browse-slice/18945/5 "2021-07-28T03:54:31Z")

</div>

hi james 😀, this is a habbit of some users, i want to keep it as it is before

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [July 28, 2021, 4:17pm UTC](https://discourse.slicer.org/t/how-to-use-left-mouse-click-drag-to-browse-slice/18945/6 "2021-07-28T16:17:05Z")

</div>

Yes, there are so many other ways to browse slices that although it would not be hard adding one more method, it would be quite low on the priority list of Slicer core developers.

If you can work in C++ then you can implement a proper solution by adding a new state in the crosshair widget (we’ll be happy to review and merge it in the Slicer core if you send a pull request). Alternatively, you can implement a somewhat hacky solution in Python, by observing low-level view interaction events.

---

<div class="post-metadata">

**Author:** ![koeglfryderyk](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/koeglfryderyk/32/14638_2.png) [@koeglfryderyk](https://discourse.slicer.org/u/koeglfryderyk)\
**Post date:** [December 8, 2024, 10:16am UTC](https://discourse.slicer.org/t/how-to-use-left-mouse-click-drag-to-browse-slice/18945/7 "2024-12-08T10:16:28Z")

</div>

here is a solution that worked fo rme (you just have to change the view names)

```python
def enable_scrolling_through_dragging(sensitivity: float = 0.1):
    # Global dictionary to track dragging state for each view
    global dragging
    dragging = {}

    sliceViewNames = ['Red1', 'Yellow1', 'Green1', 'Red2',
                      'Yellow2', 'Green2', 'Red3', 'Yellow3', 'Green3']

    def createDragHandlers(sliceViewName):
        # Create a separate dragging state for each view
        dragging[sliceViewName] = {"isDragging": False, "lastY": None}

        def startDrag(caller, event):
            dragging[sliceViewName]["isDragging"] = True
            dragging[sliceViewName]["lastY"] = caller.GetEventPosition()[1]

        def drag(caller, event):
            if dragging[sliceViewName]["isDragging"]:
                currentY = caller.GetEventPosition()[1]
                deltaY = currentY - dragging[sliceViewName]["lastY"]
                dragging[sliceViewName]["lastY"] = currentY

                if abs(deltaY) > 0:
                    position = slicer.util.getNode(
                        "*Crosshair*").GetCursorPositionXYZ([0]*3)
                    if position is not None:
                        current_view = position.GetName()
                        sliceLogic = slicer.app.layoutManager().sliceWidget(current_view).sliceLogic()
                        sliceOffset = sliceLogic.GetSliceOffset()
                        newSliceOffset = sliceOffset - deltaY * sensitivity
                        sliceLogic.SetSliceOffset(newSliceOffset)

        def endDrag(caller, event):
            dragging[sliceViewName]["isDragging"] = False
            dragging[sliceViewName]["lastY"] = None

        return startDrag, drag, endDrag

    # Loop through slice views and add event observers
    for sliceViewName in sliceViewNames:
        # Get the interactor for this slice view
        interactor = slicer.app.layoutManager().sliceWidget(
            sliceViewName).sliceView().interactor()

        # Create handlers specific to this view
        startDrag, drag, endDrag = createDragHandlers(sliceViewName)

        # Add observers
        interactor.AddObserver(vtk.vtkCommand.LeftButtonPressEvent, startDrag)
        interactor.AddObserver(vtk.vtkCommand.LeftButtonReleaseEvent, endDrag)
        interactor.AddObserver(vtk.vtkCommand.MouseMoveEvent, drag, 1.0)

def disable_scrolling_through_dragging():
    """
    Disable scrolling through dragging by removing observers from slice views.

    This function should be called after enable_scrolling_through_dragging() 
    to remove the drag event observers.
    """
    sliceViewNames = ['Red1', 'Yellow1', 'Green1', 'Red2',
                      'Yellow2', 'Green2', 'Red3', 'Yellow3', 'Green3']

    for sliceViewName in sliceViewNames:
        # Get the slice view from the layout manager
        sliceWidget = slicer.app.layoutManager().sliceWidget(sliceViewName)

        if sliceWidget:
            # Get the interactor from the slice view
            interactor = sliceWidget.sliceView().interactor()

            # Remove the observers if they exist
            if hasattr(interactor, 'startDragObserver'):
                interactor.RemoveObserver(interactor.startDragObserver)
                del interactor.startDragObserver

            if hasattr(interactor, 'dragObserver'):
                interactor.RemoveObserver(interactor.dragObserver)
                del interactor.dragObserver

            if hasattr(interactor, 'endDragObserver'):
                interactor.RemoveObserver(interactor.endDragObserver)
                del interactor.endDragObserver

    # Clear the global dragging dictionary
    global dragging
    dragging.clear()

```
