getting keyboard back from tkinter - python

I'm working on a graphical app, and at the start of the run I'd like to ask the user a single configuration question. The graphical framework (Panda3D) has ugly default dialog boxes, so I'd like to use something like tkInter to provide a modal dialog. I tried this:
import Tkinter
import tkMessageBox
root = Tkinter.Tk()
# hide the root window
root.withdraw()
config.PLAY_MUSIC = tkMessageBox.askyesno( "My App",
"Would you like this app to play music from your iTunes collection?" )
root.destroy()
This does what I want it to, but it appears to route all further keyboard events to tkInter rather than my Panda3D app. I don't need to do anything further with tk after this dialog.
I can put the tk dialog into a separate app that chains onto mine, I suppose, but I'm wondering if there's a way to kill tk and get the keyboard back without exiting my app entirely.
Update: Tried root.quit(), which does seem to get the keyboard back, but I get a "Fatal Python error: PyEval_RestoreThread: NULL tstate" crash on exit from my program, which isn't ideal.

Have you tried:
grab_release(self)
Which does: Release grab for this widget if currently set.
Where "A grab directs all events to this and descendant
widgets in the application."
as in:
root.grab_release()
Hope you haven't tried this one.

Related

Tkinter dialog box with user input AND custom buttons

Can't find this anywhere else on stack overflow.
I want to create a dialog box (on top of my main window) in tkinter that has message, a text input field and some custom buttons.
I know I can do
import tkinter as tk
from tkinter import simpledialog
master = tk.Tk()
user_input = tk.simpledialog.askstring("title", "message")
and then take the user_input from there. However, how can I make the buttons have custom text and also bind them to my own functions?
Otherwise, I was thinking of making my own dialogbox class. But that's a lot of work. Is there any way I can do this natively using any of tkinter' modules?
Regards
Hugo.

Python mouse event

I am trying to activate a function in python which will save a timestamp to a file. However, I wish to activate that function after the first mouse click that accurses outside the Tk window.
For example, after running the program I will minimize it and press on the chrome browser icon and while doing so my program will log the time stamp.
I tried to use the bind function but it works for clicks that accrue only in the Tk window
By the way, I am currently using Tkinter as my GUI platform however if there is a way to do it with another libraries please share and I will adjust my program
thanks :)
Use the <FocusOut> event:
import tkinter as tk
root = tk.Tk()
def focus_lost(event):
print("Clicked outside the window")
root.bind("<FocusOut>", focus_lost)
root.mainloop()
If you are focussed on the tkinter window (e.g. if you have clicked on it), then when you click elsewhere it will detect this as a <FocusOut> event.

Python capture events when console has focus with Tkinter

I'm building a console app, and would like to capture keystrokes in real time. The following code works perfectly until another window gets focus. From that point on, I'm not able to get back to a state where I can capture keystrokes and other events again with only the console visible.
import tkinter as tk
app = tk.Tk()
def handleKeypress(event):
key = event.char
if(key == 'q'):
app.destroy()
else:
print(key)
app.bind_all('<Key>', handleKeypress)
app.withdraw()
app.mainloop()
I've tried using various methods (grab and focus) to redirect the focus to my app. The best I was able to do was to get the Tkinter window visible and in focus with deiconify(), but I was not able to hide it again to make it as though the console is the only window.
Adding the following results in the Tkinter window appearing and disappearing repeatedly:
def lostFocus(event):
app.deiconify()
app.focus_force()
app.withdraw()
app.bind_all('<FocusOut>', lostFocus)
How can I go back to the state the application was in right after launch? Or even better, how can I force it to get all events without having to make the Tkinter window visible and in focus?
You can't do what you want. Tkinter is designed -- as are most GUI toolkits -- to only process events when it has the focus. That's the whole point of focus: for the OS to know where to send events.
The fact that it works initially is probably a bug in tkinter. Though, perhaps it can be explained by the fact that the window initially has focus, and when you withdraw the window the OS doesn't move the focus
The only way to restore focus is to make the window visible.

Python 3.3 tkinter.filedialog.askopenfile() leaves an unresponsive Tk window

I'm trying to have the user select a file through a pop-up directory browser. Looking things up suggested that I use filedialog.askopenfile(), which works but leaves a small unresponsive tk window that I'd rather not have because any attempt to interact with it causes the kernel to crash and need to be restarted.
Does anyone have any solutions or alternatives? Thanks.
This works fine:
from tkinter import *
root = Tk()
root.withdraw()
filedialog.askopenfile()

What could cause an open file dialog window in Tkinter/Python to be really slow to close after the user selects a file?

I can do the following in my program to get a simple open file dialog and print the selected file path. Unfortunately it doesn't go away right away when the user selects the file, and stays around for over 5 minutes. How do I make the window disappear immediately once a selection has been made before executing more python code? After the Tkinter code I do try to import some video using OpenCV which I think may be causing the slowing. My OpenCV code does execute properly and I don't think there is a problem with that alone (i.e. some interaction is causing the error & maybe some intensive process is started before Tkinter wraps up its GUI dialog).
import Tkinter as Tk
import cv2
from tkFileDialog import askopenfilename
root = Tk.Tk()
root.withdraw() # we don't want a full GUI, so keep the root window from appearing
filename = askopenfilename() # show an "Open" dialog box and return the path to the selected file
print(filename)
cap = cv2.VideoCapture('video.mp4') # this works just fine
I am using Python 2.7 and Mac OS X 10.9 if that is useful.
[EDIT: This does not seem to be a problem for all, but it is for me, so I am changing the question to also include debugging the problem. I don't want anything to execute until the Tkinter open file dialog window is done closing in the GUI. It seems that a subsequent step in my program (an open cv video import) could somehow be causing Tkinter to slow things down, so I want to ensure it does close before any new process is started. Again, the Tkinter window does actually close after 5 minutes...]
I was having some trouble with Tkinter dialog boxes. Like you, the dialog just sat there after I had selected a file. I didn't try leaving it for very long, it may have disappeared after 5 minutes as you said your's did. After lots of random experimentation I found that calling root.update() before the askopenfilename() line seemed to fix it.
For reference, this is the code I was testing with:
import sys
from tkinter import *
from tkinter import filedialog
#instantiate a Tk window
root = Tk()
#set the title of the window
root.title('Tk test')
# I don't know, what this does, but it fixes askopenfilename if I use it.
root.update()
print(filedialog.askopenfilename(title='dialogue? surely.'))
Exactly the problem I had - sometimes the file dialog would go away after a while, sometimes not. But it always seemed to block a later status windows. Adding the root.update() fixed both problems immediately.

Categories