Confusion about mouse_button_pressed_event vs mouse_button_released_event vs mouse_moved_event

edited January 27 in Verification

Hello,

I'm attempting to create a plugin (in Klayout 0.30.5) that loads a second layout if some conditions are triggered, and want to be able to use the plugin there. I'm having a bit of trouble understanding the structure of plugins and when the mouse_button_pressed_event etc. are actually called.

Here's the relevant skeleton of my code:

# $description: test
# $show-in-menu
# $menu-path: tools_menu>end("Test").end

import pya as kl

class PluginTestFactory(kl.PluginFactory):
    def __init__(self):
        self.add_submenu("menu_name", "inset_pos", "title")
        self.register(29318, "plugin_name", "test_plugin")
    def create_plugin(self, manager, dispatcher, view):
        return PluginTest(view)
class PluginTest(kl.Plugin):
    def __init__(self,view):
            self.curr_annot = kl.Annotation()
            self.curr_annot.p1 = kl.DPoint(0,0)
            self.curr_annot.p2 = kl.DPoint(0,0)
            self.curr_annot.fmt = ""
            self.curr_annot.fmt_x = ""
            self.curr_annot.fmt_y = ""
            self.curr_annot.outline = self.curr_annot.OutlineBox
            self.curr_annot.style = self.curr_annot.StyleLine
            view.insert_annotation(self.curr_annot)
    def mouse_button_pressed_event(self, p, buttons, prio):
        print("hello")
    def mouse_button_released_event(self, p, buttons, prio):
        self.match()
    def mouse_moved_event(self, p, buttons, prio):
        self.curr_annot.p2 = p

    def match(self):
        big_menu = kl.QDialog()
        big_menu.layout = kl.QGridLayout()
        containing_layout = kl.QWidget()
        self.layoutwidg = kl.LayoutViewWidget(containing_layout)
        cv = self.layoutwidg.view().create_layout(True)
        viewing_layout = self.layoutwidg.view().cellview(cv).layout()
        big_menu.layout.addWidget(self.layoutwidg,0,0,1,1)
        big_menu.show()

if __name__ == "__main__":
    PluginTestFactory()

When I click on the Tools>test menu button, a "test_plugin" button appears on the toolbar. The annotation appears and follows my mouse around before pressing the test_plugin button; I expected the annotation to appear, but the fact that it follows my mouse around implies that the mouse_moved_event is being called implicitly.

When I click the button in the toolbar, the "Basic Editing" pane pops up (why does that happen, by the way? It's annoying.), but no other effects occur; clicking and dragging and releasing does nothing. But when I open the debugger, I can put a breakpoint on the mouse_button_pressed_event and the mouse_button_released_event lines and it stops at both of them. If I step past the self.match() call, nothing else happens.

But if I step into the self.match() call and let it run, it opens up the QDialog I asked for. Within this QDialog, it appears that the mouse_button_pressed_event is completely inactive, whereas the mouse_button_released_event and mouse_moved_event calls are still active (in the sense that it stops at a breakpoint in the mouse_button_released_event function).

This is all very confusing to me, and I would like to understand what's going on. Is there some sort of infinite recursion being headed off by avoiding the self.match() call when the debugger breakpoint is absent, and is that why it isn't run?

The simplest question that would move me forward is: How do I force the mouse_button_pressed_event to be recognized in the layout in this pop-up window?

Thanks so much!

Noah

Comments

  • Hi Noah,

    did you check the documentation?

    https://www.klayout.de/doc-qt5/programming/application_api.html#k_11 explains the concept of the mouse events. Specifically it says:

    If no receiver accepted the mouse event by returning true, it is sent again to all plugins with 'prio' set to false. Again, the loop terminates if one of the receivers returns true. The second pass gives inactive plugins a chance to monitor the mouse and implement specific actions - i.e. displaying the current position.

    Here is more example code: https://www.klayout.de/doc-qt5/code/class_PluginFactory.html

    There are packages implementing Plugins, for example this one: https://github.com/s910324/SplitShapePlugin. You can study that one for example. It is well made.

    Matthias

  • edited February 2

    Thanks for your reply! My two questions are:
    1. It says in the documentation that

    When a LayoutView is created, it will use the PluginFactory to create a specific Plugin instance for the view. When the tool bar button is pressed which relates to this plugin, the plugin will be activated and mouse or other events will be redirected to this plugin.

    However, when I open this new LayoutView in the pop-up window, there is no tool bar button to press, so the plugin never gets activated (and the Select tool appears to always be activated). If I re-click on the button in the main window, it doesn't seem to activate the plugin in the pop-up window. And if I manually call self.activated, nothing seems to happen. So I'm asking how to activate the plugin, either manually or through code, in this new LayoutView.
    2. It seems that in this case, the other mouse events are working as intended, but I cannot seem to get mouse_button_pressed_event to be called with prio=False. I saw at this link that there had been trouble in the past with mouse_button_pressed_event not working perfectly, so I'm concerned there might be a bug in its implementation, even though that link says it's been fixed.

    I am sorry because these seem like basic questions, but it feels like what I'm seeing is counter to the documentation. Thanks so much for your help!

    (P.S. I'm sorry I posted this in the Verification category; I could not figure out how to either delete the topic or change the category after it was posted.)

    Noah

Sign In or Register to comment.