It looks like you're new here. If you want to get involved, click one of these buttons!
Is it possible to have an example of code that capture a mouse click and its location (ideally in Python but ruby is also fine).
For instance: on click, print “You have clicked at the location X,Y of the design”
My main target is to make a small script that can ask you to click somewhere and set this new point as a new origin for the design. If it is a function that already exists, also please let me know.
Thanks a lot!
Comments
Hi Jonathan,
you can capture mouse events in a "plugin". Below is a small piece of code illustrating how this works. Basically you create a plugin to implement a new mode. If selecting this mode by clicking on the respective tool bar entry, you can capture mouse events until the mode becomes inactive again.
Plugins are slightly clumsy currently. For example, there is no method to activate a mode from your code. Hence, the only way to integrate your mode is through toolbar buttons. When I'm debugging the code, I have to execute the macro twice before the code becomes effective - I did not debug this yet as it's just a little bit annoying.
And please note the workaround for bug 191.
Matthias
Hello Mathias, Thank you very much for this answer! and sorry for coming back on it so late.
I would like to now share the program I now have:
1- ideally I could snap the cursor to a given grid, is it visually possible?
2- to move the layout I use layout transformation and zoom at the corrected location, is there maybe a more concise way?
3- to release the tool I call the PluginFactory again, I made a thread which is also more general on this topic
here is the program:
Hi Jonathan,
thanks for the hint about the class order.
Regarding your points:
1.) There is no cursor - actually there is just the mouse pointer and it can't (or should not) be manipulated. So if you want a snapping cursor, you have to implement a marker and move that with the mouse. You could then set the mouse cursor to invisible and this way you'd basically get your own cursor. I have not tried this yet - probably there is a lot of event handling - i.e. when the mouse enters or leaves the canvas etc.
2.) Moving the layout is a valid operation, but this will not work when you're inside a child cell. So either you catch this condition as an error or implement a transformation at cell level (which is not as straightforward as layout transformation as there is no single method for this yet)
3.) See my answers in that thread
Matthias
Hello Matthias,
Thanks again for the support: here I share again the result with the update:
deactivated(self)
The issues known/found:
Ah ... now the posts connect :-)
Please see my comments in the other post.
Thanks for sharing this code and best regards,
Matthias
Hi,
Sorry for not opening a new thread, I think that the answer will be good to be posted under the current thread for completeness.
Let's say that we want to use buttons states for several jobs, and e.g. pya.ButtonState.RightButton click to deactivate the plugin. I tried to use self._destroy() inside mouse_click_event but KLayout crashed, so I imagine that this is not the correct way of doing it.
So, my question is, which is the correct way to deactivate the plugin through a mouse button click?
Thanks in advance,
Chris
Hi Chris,
well, a crash should not happen - but there is a always a risk of things going out of sync when an object is destroyed. I'm trying the harden the code against this, but there are too many paths to destruction ...
Regarding your question:
pya.MainWindow.instance().menu().action("@toolbar.select").trigger()
is one way - I personally preferpya.MainWindow.instance().cancel()
.The latter function will also clear the selection which is a good thing to do when you deleted something or messed with the database in other respects.
And undo/redo support is easily added by using
LayoutView#transaction
/LayoutView#commit
.Kind regards,
Matthias
Hi all,
@Matthias, I tried your suggestions unsuccessfully, but I managed to deactivate the plugin destroying the instance, by running
SetOriginOnMouseClickPluginFactory.instance._destroy()
instead ofself._destroy()
, without making KLayout crash. Is a valid way of doing it?UPDATE: KLayout now crashes when I reactivate the plugin, so it cannot be taken as a viable solution.
Chris
@crizos : If I understood you wish to have a sequence of actions on clicks and only quit the plugin at the end of it? what I would do for that would be to set up a variable which increment on each click and tells how far you are with the clicks.
on the last click exit/change tools as @Matthias mentioned.
the complete escape sequence in the code is:
good luck, and we are always interested in resulting codes
@jonathan : Yes, you are correct, and as for the counting variable, I don't have finite steps in my implementation, but even so, I still think that I would have the same problem in reactivation.
I want to enable the plugin e.g.
menu.action('somewhere.something').triger()
and after an arbitrary sequence of events User right clicks and deactivates the plugin. I saw your example and tried your approach but it didn't work. After some (re)search in the documentation, I also saw the_object_._destroy()
but that method makes KLayout crash, which means that is a no-go solution.Also, it seems that I don't have access to
deactivated
method, maybe that helps with my problem. The sample code I use is part of the one that @Matthias posted at the second comment from the current thread.My code sample:
Best regards,
Chris
Hi @crizos,
when you are finished with your clicks just click on a another tool and you are set, you need a trigger anyway to say that you are done with your clicks,
However you need to ungrab mouse when the tool is desactivated otherwise you will have a bug indeed...
This is indeed a bug in my previous code!
I am posting now a new code with this bug corrected and few other corrections:
Hi @jonathan,
Thank you for reposting the code,
Yes, the bug, or the reason why my implementation doesn't work, may rest in the difference that my plugin does not have a tool entry in the toolbar. The triggering should be happening from a function call, in an entirely different area, and as it said, the plugin should be deactivated with a mouse click. If you see, I ungrab the mouse and use the methods that you and @Matthias recommended.
Also, I forgot to say something that may help. Without the toolbar entry,
prio
is always False, so I didn't include it in my implementation.Best regards,
Chris
Hi @crizos my post just crossed your edit, I will look at the code later but so far I only managed to grab mouse click from the pluginfactory which are tools, so I am not sure if there is a way to separate them.
Hi again @crizos,
I tried the following code and it worked very good with my script:
when you click on the select tool, it will finishes the tool or you can finish it in code with:
In your code you have to ungrab mouse when deactivated
Hi @jonathan,
You are right, thank you very much for this answer! This unlocked my misunderstanding issue about deactivation! I had never tried to hide the plugin from the toolbar itself, so it made things more complicated than it should. I still have KLayout crashing on re-activation but I should check in my code. In the example above it works fine for me also
Thank you both,
Chris
Hi @crizos you are welcome, but I have to also thank you for highlighting the missing ungrab mouse which is quite important there.
Thanks for these posts - my understanding of "deactivation" wasn't "hiding".
I'd still like to debug the crash. Taking the above code from Dec/10, can I modify it in a way so I can reproduce the crash?
Thanks,
Matthias
the issue was simply that we really need to ungrab mouse when the tool is deactivated:
If we forget to ungrab mouse and we switch tools then there is a bug, probably a conflict between the new mouse grab from the new tool and the old mouse from our own tool.
You are right that wasn't the issue. Firstly I wanted to move the plugin from toolbar to menu, as Tools option, so I set variable
has_tool_entry
to False and then I usedadd_menu_entry
.So, from what I understand, if
has_tool_entry
is False, theprio
attribute ofmouse_moved_event
never returns True (that means is never triggered?).Because of these issues, I won't add a Tools entry and I will use Jonathan's suggestions for the plugin's toolbar visibility.
My mistake was that I thought that both 'menu' and 'tool' entries work the same way. In my sample, the plugin was never actually triggered, so normally I couldn't deactivate something that was not already activated. I think that is the reason that KLayout crashes.
Best regards,
Chris