Python tkinter button.invoke method trouble - python

I'm playing about with a motion controller, therefore to "click" a button I am finding out which button is closest to the middle at any given point and then using the button.invoke() method.
I am confident the buttons and setup is working, because whenever I click the buttons - they work fine. However, When the button is called via the "button.invoke" method the whole thing just freezes up.
Other information which may be useful:
- The gui is being updated in it's own thread through the .mainloop function.
- Everything works fine when being clicked by a mouse
- The button.invoke() method works fine - when doing a simple print operation. It only freezes when switching frame.
Any help would be great, thanks.

Are you saying that mainloop runs in a separate thread from where you create the widgets? If so, that's your problem. You can only ever call tkinter functions from one thread.

Related

Window moving behind other open windows when button pressed (Python with Tkinter)

Apologies if this is a completely easy fix and I've just missed it. I am learning Python and I am trying to develop a GUI alongside my backend code using Tkinter. This is completely foreign to me and I have recently come across the problem that when I press my buttons there is a very small chance that it will make my window move behind all other open programs.
I am not entirely sure what is causing this but my guess is it stems somehow from one of two functions I have; one meant to minimise the main root window and the second to reveal it. However, these functions are not called in any place in my program that I would not expect them and the windows being minimised are not the root window (which my two functions act on).
I have both functions added below (hopefully, I am pretty new to SO) but if any additional code is needed I will supply it. I have quite a bit of code and everything else functions perfectly so I didn't want to post all my code is all.
There is no particular combination of button presses or buttons in particular which cause it, it appears to be any of them seemingly at random. It sends whatever window I have up to the taskbar.
def revealMenu():
root.update()
root.deiconify()
def hideMenu():
root.withdraw()

Function running only after tkinter windows has been closed

I'm learning how to program in Python and use the PIL (Pillow) in order to create small bots which can recognize changes in the screen in order to execute repetitive commands (keyboard presses with pynput module).
I did a small GUI with Tkinter in order to get user information regarding the parameters which the user is going to use (Entry widgets) at their use of the bot and I also need a few buttons for enabling/disabling certain parts of the code (i'm using check buttons and using boolean logic in order to enable/disable) and also for enabling the main function of the bot (which is to press a button once it recognizes a certain change at the screen).
What I am currently experiencing is that the once I run my program, it opens up my GUI and all that a user would see but it doesn't execute my main function, it only executes the main function AFTER I close the GUI.
I'd love to post my code but it exceeds 220 lines and it would probably become even more confusing.
So, long story short, is it a kind of error which happens a lot when inexperienced programmers try to create softwares with tkinter? If yes, what causes it and how can it be fixed?
I appreciate any help you guys can get me. :]
...creates frames, widgets, entries...
mainHealerVar = IntVar()
main_healer_check = Checkbutton(root, text="Enable the bot", variable=mainHealerVar) #this should mean that when i press this checkbutton it'll enable the bot and perform the repetitive commands for as long as it stays checked
... some more buttons/code...
root.mainloop() #right after I stop setting up the GUI, I place this function
... make logic in order to know which part of the repetitive functions to execute...
if mainHealerVar.get() == 1:
mainHealFunction() #function to check if the checkbutton is still pressed (if it is, it should execute mainHealFunction()
It was supposed to execute the repetitive commands by the pynput module as soon as i clicked on the enabling Check-button, but it doesn't execute anything until I close the GUI, then it starts to execute the repetitive commands. I have also tried using a while loop instead of an "if" at the end, but ended up with the same result.

Preference window destroyed when closed - Glade, Gtk, Python

I am experiencing a problem with my program wherein when I close my preference window via the close button it will not reopen properly.
I open the preference window by going "file>preferences" which works just fine...
However when I close it via the close button in the top right...
It will no longer open properly. For the record the back button which I have connected to my close_pref_window function works just fine.
To open the window I go "file>preferences" which triggers a function that just preference_window.show_all() and to close it I call pref_window.hide(). I also have the delete_event connected to the same function as the back arrow so I don't understand why the one works and not the other. I am thinking that the close button destroys the window first and then calls the function... Any suggestions?
Thank you to #theGtknerd and #andlabs for your help. As theGtknerd pointed out the delete-event signal will continue to execute its default action unless your function includes return True at the end.
def pref_window_close(self, *args):
self.pref_window.hide()
return True
Thanks again for the help :)
(I apologize my question was answered a while ago, I was just mis-reading their comments :P)

Checking user idle in PyQt by examining mouse clicks on the GUI

I am trying to implement a feature such that if the user havn't interact with the GUI for some time X, I will stop some functionality of the GUI.
Currently I have a time stamp set up so that if any of the button is not clicked in X seconds, the GUI will terminate some functionality
button1.triggered.connect(keep_alive)
button2.triggered.connect(keep_alive)
....
buttonN.triggered.connect(keep_alive)
As you can see, this is not really elegant, and doesn't scale as the button increases. Therefore I am currently investigating another method such that I monitor the mouse clicks
mouse = app.mouseButtons()
if mouse != Qtcore.Qt.NoButton:
#keep_alive
I think this is a little hacky, but it will work for the functionality I envisioned, however, I do not know how to insert this to the execution loop of the QT.
Any suggestions will be appreciated
You must intercept the mouse events by reimplementing the mousePressEvent.
http://qt-project.org/doc/qt-4.8/qwidget.html#mousePressEvent
To make sure that it won't affect your other functionalities you'll need to propagate it to the parent widget. Read more details: https://www.qt.io/blog/2006/05/27/mouse-event-propagation
I would proceed by implementing it in the main window and make sure all mouse events are propagated to it.

Python GUI Events

I'm sure this question has been asked many times before, so I apologize in advance. I simply cannot find the answer via google or searching stack overflow.
I'm working in python with the wx library. I simply need a wx.EVT_CHAR to be thrown anytime a user presses a key, no matter the focus. How can this be accomplished? Is there a way to bind all widgets? Or a way to always throw an event when application receives a key press?
I tried binding the application itself, the main frame, and the main panel. None of these have accomplished the job of always throwing a wx.EVT_CHAR when a key is pressed.
I was able to solve my problem by writing a recursive method that sets every widget to receive characters and binds every widget to my callback function. It's pretty simple, but took me a bit of googling to realize that not every widget can inherently receive text events (such as a button). Hopefully this will save someone some time in the future. It should be noted that only widgets that are children or subchildren of the parent window passed will be bound to the callback method.
def __RecursiveBinding(self, parent):
try:
parent.Bind(wx.EVT_CHAR, self.CharInputCallback)
parent.SetWindowStyleFlag(wx.WANTS_CHARS)
parent.Refresh()
children = parent.GetChildren()
if(children):
for child in children:
self.__RecursiveBinding(child)

Categories