Double Click Events are not registered by Observer?

Currently trying to perform an annotation procedure with my mouse. Basically, in my custom annotation mode, rotation of the world is disabled so I can perform custom annotations with the mouse (as of now, only record the world coordinates via ray tracing, so I track the coordinates and resize objects dynamically later on). Reason is that I do not want the world to rotate while I am drawing my own annotations. That would mess up the custom annotations.

  • Left Press Event
  • Left Mouse Release Event
  • Mouse Move Left Button
  • Double Click

Adding an observer during annotation mode for all those for events, seems to work (rotations is effectively disabled with mouse movements, for example when left clicking and dragging).

However, when I double click and release, and left click and drag again, the world suddenly rotates again and coordinates are no longer printed, which is not intended; it is like it is disabling my annotation mode, while other mouse events do not do it. Only double clicking seems to do it. To enable this custom annotation mode, I have to enable it again to handle my custom mouse events.

In other words, the observer is NOT able to observe the double clicks, but seems to reset the interactor style when double clicking? The logic to enter the double click is detected properly, however. But not by VTK.

from coordinates import Coordinates
import time

class MouseHandler:
    def __init__(self, plotter, annotation_handler):
        self.plotter = plotter
        self.annotation_handler = annotation_handler
        self.coordinates = Coordinates(plotter)
        self.is_dragging = False
        self.start_world_pos = None
        self.end_world_pos = None
        self.last_click_time = 0
        self.click_interval = 0.5  # 0.5 seconds for double click

    def left_button_press(self, obj, event):
        current_click_time = time.time()
        if current_click_time - self.last_click_time <= self.click_interval:
            # Detected a double click
            self.left_button_double_click(obj, event)
            self.is_dragging = False
        else:
            # Handle as a single click
            if self.annotation_handler.annotation_mode:
                self.is_dragging = True
                self.drag_start_world_pos = self.coordinates.screen_to_world(self.plotter.interactor.GetEventPosition())
                print(f"Start Dragging at World Position {self.drag_start_world_pos}")
        self.last_click_time = current_click_time

    def mouse_move(self, obj, event):
        if self.annotation_handler.annotation_mode and self.is_dragging:
            current_screen_pos = self.plotter.interactor.GetEventPosition()
            current_world_pos = self.coordinates.screen_to_world(current_screen_pos)

            # Retain the Z-coordinate from the drag start position
            drag_world_pos = (current_world_pos[0], current_world_pos[1], self.drag_start_world_pos[2])
            print(f"Dragging at World Position: {drag_world_pos}")

    def left_button_release(self, obj, event):
        if self.annotation_handler.annotation_mode and self.is_dragging:
            self.is_dragging = False
            current_screen_pos = self.plotter.interactor.GetEventPosition()
            current_world_pos = self.coordinates.screen_to_world(current_screen_pos)

            # Final position with the same Z-level as the start position
            end_drag_world_pos = (current_world_pos[0], current_world_pos[1], self.drag_start_world_pos[2])
            print(f"End Dragging at World Position: {end_drag_world_pos}")
            self.drag_start_world_pos = None

    def left_button_double_click(self, obj, event):
        print("Double click detected")
from mouse_handler import MouseHandler
import vtk

class AnnotationHandler:
    def __init__(self, plotter):
        self.plotter = plotter
        self.annotation_mode = False
        self.mouse_handler = MouseHandler(plotter, self)
        self.default_interactor_style = self.plotter.interactor.GetInteractorStyle()
        self.custom_interactor_style = CustomInteractorStyle(self.mouse_handler)

    def toggle_annotation_mode(self):
        if self.annotation_mode:
            self.disable_annotation_mode()
        else:
            self.enable_annotation_mode()
        self.annotation_mode = not self.annotation_mode

    def enable_annotation_mode(self):
        print("Enabling annotation mode")
        self.plotter.interactor.SetInteractorStyle(self.custom_interactor_style)

    def disable_annotation_mode(self):
        print("Disabling annotation mode")
        self.plotter.interactor.SetInteractorStyle(self.default_interactor_style)

class CustomInteractorStyle(vtk.vtkInteractorStyleTrackballCamera):
    def __init__(self, mouse_handler):
        super(CustomInteractorStyle, self).__init__()
        self.mouse_handler = mouse_handler

        self.AddObserver("LeftButtonPressEvent", self.mouse_handler.left_button_press, 1.0)
        self.AddObserver("MouseMoveEvent", self.mouse_handler.mouse_move, 1.0)
        self.AddObserver("LeftButtonReleaseEvent", self.mouse_handler.left_button_release, 1.0)
        self.AddObserver("LeftButtonDoubleClickEvent", self.mouse_handler.left_button_double_click, 1.0)

In my main.py;

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        # Load the UI
        uic.loadUi('main.ui', self)
        self.plotter3D = QtInteractor(self.AllView)
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.plotter3D.interactor)
        self.AllView.setLayout(layout)
        self.plotter3D.set_background('black')
        self.plotter3D.add_axes()
        self.color_gradient_applied = False
        self.current_lidar_data = None
        self.annotation_handler = AnnotationHandler(self.plotter3D)
        self.mouse_handler = MouseHandler(self.plotter3D, self.annotation_handler)

        self.Annotate.clicked.connect(self.annotate)

  def annotate(self):
      # Toggle Custom Annotation Mode to perform custom mouse events
      self.annotation_handler.toggle_annotation_mode()

Thank you for your support.