Tkinter TkMessageBox not closing after click OK
Asked Answered
P

5

8

I have created a script in Python which notifies me at a given event. I am using the following function to produce the warning window:

def window_warn():
    '''
    This function will throw up a window with some text
    '''
    #These two lines get rid of tk root window
    root = Tkinter.Tk()
    root.withdraw()
    #tkMessageBox.deiconify() 
    TkMessageBox.showwarning("New Case", "You have a new case\n Please restart pycheck")
    return

The window draws fine, but when I click ok, the window stays in place with the button depressed. Im using xfce. Is there anyway to get the window to close after ok is clicked?

A comment indicated this may be to do with surrounding code, so for completeness:

print "Just started newcase check"
while True:
    if "Uncommitted" in webpage:
        print "oh look, 'Uncommitted' is in the url returned from the last function"
        #If this hits we call a notification window
        window_warn()
        print "sleeping"
        time.sleep(10)

        webpage = scrape_page()
    else:
        print "nothing"
        time.sleep(20)
        webpage = scrape_page()
Phonotypy answered 10/7, 2013 at 16:3 Comment(2)
I just added the code which is calling the function for contextPhonotypy
Also, when I run this in the interactive shell it works fine. Not sure if it is because I am not capturing the return okPhonotypy
O
9

Try calling root.update() before returning from the function. That will process all pending Tk/X window events.

(ideally, you'd establish a main event loop before displaying the window, but that assumes that your entire program is event driven, which may not always work.)

Ornithine answered 21/7, 2013 at 22:5 Comment(4)
Thanks,This seems to be exactly it!Phonotypy
Sorry, would you mid explaining what you mean by main event loop? The program scans a web page every minute.Phonotypy
Tkinter programs usually (but not always) consist of Tk "on the top" and your code being run by callbacks -- i.e. you set up the Tk part first, call mainloop, and then wait for Tk to call you, usually in response to the user interacting with the program. That's probably a bit impractical for your case, though.Ornithine
Ahh yea. That makes wayyy more sense. Thanks!Phonotypy
M
0

You have to call root.mainloop() to enable the program to respond to events.

Mead answered 17/7, 2013 at 11:15 Comment(2)
So I called root.mainloop() right after tkmb.showwarning("New Case", "You have a new case") and it seems to just hang, does not do anything. Does it need to be called in a certain way? ThanksPhonotypy
It has to be running before you open the dialog, since opening the dialog blocks until the dialog is dismissed.Mead
F
0

One problem on your code is that you create a new Tk element each time you call the function window_warn. This might not be the cause of your issue, but creating multiple Tk elements is a bad practise that should be avoided. For instance, initialize the root element at the beginning and leave only the call to showwarning:

root = Tkinter.Tk()
root.withdraw()

def window_warn():
    '''This function will throw up a window with some text'''
    tkMessageBox.showwarning("New Case", "You have a new case\n Please restart pycheck")
    return

print "Just started newcase check"
while True:
    # ...
Filmdom answered 19/7, 2013 at 15:21 Comment(2)
I see your point here. If I call the root outside the function I can't runt the root.update() on it within the function. Perhaps I have it set up in the incorrect way, and I should have a first run section to initially kick off the root = Tkinter.Tk(), Im running within a terminal box for now anyway so it seems to work fine at the moment (no duplication of windows)Phonotypy
The code in the function can still access root if it's defined inside the same module (this is called a "global" variable in Python, even though it's only directly visible to code inside the same module). I don't see any big harm in recreating the Tk root window, though.Ornithine
B
0

I did it tis way:

import Tkinter as tk
import tkMessageBox
root = tk.Tk()
root.withdraw()
t = tkMessageBox.askyesno ('Title','Are you sure?')
if t:
    print("Great!!!")
    root.update()
else:
    print("Why?")
    root.update()
Bifocals answered 28/2, 2018 at 12:27 Comment(0)
C
0

Another solution is to track if the tk.messagebox has occurred, and if it has just break/continue/pass to skip over the re-occurring tk.messagebox:

Flag = False
if Flag: 
    messagebox.showerror("Error", "Your massage here.")
    Flag = True
else:
    break

I propose this because I had issues with other solutions proposed on StackOverflow as I don't have a dedicated root.mainloop() but only have self.mainloop() within the class Root()

My root looks like this and the massage event is generated within some of the inner classes, where I have no access to self.root:

    class Root(tk.Tk):
        def __init__(self):
            tk.Tk.__init__(self)
            ....
            class 1..
            class 2..
            self.mainloop()
Cyrstalcyrus answered 30/3, 2018 at 12:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.