Tkinter quit() freezes window - python-2.7

I got a code that creates a hidden main window in Tkinter (root, Tk object) and than a Toplevel window. I use after() to pass the mainloop() to the rest of the code, but the window just freezes. I don't want do destroy the app, just to run the rest of the code.
I set the milliseconds in after to 10,000 and noticed that only after 10 seconds, when it prints After mainloop, the window freezes/.
Does anybody know why and can I do to make it work?
root = Tk()
top = Toplevel()
top.after(10000, top.quit)
top.mainloop()
print 'After mainloop'
Thank you very much

It will be hard for anyone to debug with what you posted i will suggest doing top.iconify() rather to hide the app. assuming chat is window.

Related

WxPython - Inaccurate modal windows behavior

I encounter some annoying behavior with modal frames in WxPython.
As we all know, when a modal window shows up, it appears on foreground (on top of the main window) and the main window should become inaccessible (no response to click for example).
This is working as expected with nested WxFrames until using the Windows start (status)bar.
If user clicks on main frame on Windows bar, it appears on top of the second frame, which is totally inaccurate as user does not understand what's happening and why the window is inaccessible.
The first solution coming on my mind is to bind activation event of the first frame, and set programmatically (& systematically) the second frame to foreground. However it appears to me weird that this behavior is not already done naturally by WxPython.
Does anyone have any idea or any native / generic solution for that?
As I suggested in my question, I binded activate event I raise all children window. This works as expected. We can first go to top level window and starting to raise from the first window to raise always all children frames. But always it's strange for me that it's not managed naturally by wxPython.
def __init__(self, parent):
wx.Frame.__init__(...)
...
self.Bind(wx.EVT_ACTIVATE, self.on_activate_window)
def on_activate_window(self, event):
"""
Set modal windows to foreground by their hierarchical order
"""
self.set_children_to_top(self.GetChildren())
def set_children_to_top(self, children):
"""
Loops all children of the given windows, if any other modal window is found, it raises the new window to foreground
"""
for child in children:
if isinstance(child, wx.Frame) and child.is_modal:
child.Raise()
try:
child_window = child.GetChildren()
if child_window:
self.set_children_to_top(child_window)
except AttributeError:
continue
It is much better to use wx.Dialog when you need a modal window, as it is designed from the start to behave that way. In fact, because of the inconsistencies the MakeModal method has been removed for frames, although if you really need to do it that way there is a workaround.

How do I run a method from TKinter without having the GUI freeze up?

Supposed I have a method that is run when a button is pressed in TKinter. This method opens up an external application (i.e. Excel, Powerpoint, etc. The application my program opens takes a little longer to open which is why I need the loading dialog)
I am trying to open up a little custom tk.toplevel loading dialog that will display and takefocus while the external application loads.
However, whenever TKinter runs the method to open the application, the whole thing freezes up and my loading dialog is only visible after the application finally opens.
Is there a way to show my loading dialog while at the same time opening the application in the background?
Not at the same time. Instead open the dialog first and then call the method that opens the other application. You will have to enforce the drawing of the dialog by calling update_idletasks before the method that will freeze the GUI, otherwise the dialog won't be drawn until the program is idle and it will be too late.
In this example I used time.sleep to simulate a task that keeps the application busy and the GUI frozen.
import time
import tkinter as tk
class App():
def __init__(self):
self._root = tk.Tk()
b = tk.Button(self._root, text='Click me', command=self.onclick)
b.pack()
def run(self):
self._root.mainloop()
def onclick(self):
dialog = tk.Toplevel(self._root)
tk.Label(dialog, text='Loading...').pack()
dialog.update_idletasks()
self.this_takes_a_long_time()
dialog.destroy()
def this_takes_a_long_time(self):
time.sleep(5)
App().run()

How to 're-run' the mainloop in Tkinter

I've been asked to make a Chat program using Tkinter. For the final part, I'm supposed to have the Chat window open, which has one Entry field, one Button (SEND) and a Text Widget to display the chat log. This is my first week learning Tkinter, and I've been told in class that the mainloop() is an infinite loop as long as the user doesn't close the window or write root.quit(). So in the chat window, I'm supposed to check for new messages every 10 seconds. Is it possible to do that in the mainloop()? If yes, please let me know how, because I have no idea how that can happen since the stuff before the mainloop() is read only once. For example, something like a print statement is printed only once, even though the mainloop() is an infinite loop.
You can call the after method of the root window to call something in the future. If that function itself calls after, you can set it up so that your function runs every 10 seconds forever.
def check_for_messages():
<your code here>
root.after(10000, check_for_messages)
Call that function once before calling mainloop() and it will run every 10 seconds for as long as mainloop() is running.

How to keep the window focus on new Toplevel() window in Tkinter?

I am currently writing a win32gui python27 application (I'm running win7). I am wondering if it is possible to create a new window from my mainloop() and KEEPING the focus on it, possibly by stopping the mainloop and deactivating the root window. In a sort of pseudo code example:
root=Tk()
#put in some widgets, such as statusbars, tkfileDialog widgets etc...
O=Toplevel()
OptionMenu(O) #wait for user to make his choices; btw: OptionMenu is a class...
tkFileDialog.askdirectory(...) #THEN interpret this line
Basically, I'd like to achieve what most of the widgets in tkfiledialog and tksimpledialog do:
To steal the focus from the main window (not just the console focus, the wm focus) and to resume the mainloop until AFTER everything in, for example, OptionMenu has been resolved. I hope I could make my goals clear to y'all, I just started Tkinter programming a couple of weeks ago and may confuse and misinterpret some concepts behind it....
That's all, folks!
The concept you are looking for is called a "grab". Tkinter supports grabs with several methods. For example, to set a local grab on a toplevel you would do my_window.grab_set(). A local grab is where this window grabs the focus from all other windows in your app, but only for your app.
You can also do a global grab, which effectively freezes your entire display except for your specific window. This is very dangerous since you can easily lock yourself out of your own computer if you have a bug in your code.
Grabs do not deactivate the mainloop function. This must be running for your window to process events. It simply redirects all events to the window that has the grab.
For more information, read about grab_set and other grab commands here: http://effbot.org/tkinterbook/widget.htm#Tkinter.Widget.grab_set-method
None of the above suggestions worked for me, on Mac OS El Capitan. But based on those hints, this does:
class Window(Tk.Toplevel):
...
def setActive(self):
self.lift()
self.focus_force()
self.grab_set()
self.grab_release()
...
grab.set() is much to aggressive for my needs and blocks normal window operations. This answer is to make one Tkinter Window pop up overtop of other Tkinter windows.
In my app I have a large window toplevel which calls a much smaller window top2 which initially appears on top of toplevel.
If user clicks within toplevel window it gains focus and smothers much smaller top2 window until toplevel window is dragged off of it.
The solution is to click the button in toplevel to launch top2 again. The top2 open function knows it is already running so simply lifts it to the top and gives it focus:
def play_items(self):
''' Play 1 or more songs in listbox.selection(). Define buttons:
Close, Pause, Prev, Next, Commercial and Intermission
'''
if self.top2_is_active is True:
self.top2.focus_force() # Get focus
self.top2.lift() # Raise in stacking order
root.update()
return # Don't want to start playing again

Qt: How do I get the currently running window?

I'm writing a test app which simulates key presses and I would like to get what window is displayed after each key presses. Here's the code block.
std::auto_ptr<MyForm> pForm(new MyForm(3,3));
QTest::keyPress(pForm.get(), Qt::Key_0);
After pressing 0 here, A window is gonna show up and I would like to check what window it is so I could QCompare/evaluate it later.
Any Ideas?
Updated:
I'm getting a segmentation fault when I use
std::auto_ptr<MyForm> pForm(new MyForm(3,3));
QTest::keyPress(pForm.get(), Qt::Key_0);
QWidget *pWin = QApplication::activeWindow();
QCOMPARE(pWin->windowTitle(), QString("My Second Menu"));
If all your windows have been created through your application, you can use the QApplication class.
By example, the activeWindow() function returns the widget that have the input focus. But there's a lot of other functions that can help you.
Hope that helps