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()
martineau
  • 119,623
  • 25
  • 170
  • 301
Rqomey
  • 482
  • 4
  • 12
  • I just added the code which is calling the function for context – Rqomey Jul 18 '13 at 08:19
  • Also, when I run this in the interactive shell it works fine. Not sure if it is because I am not capturing the return `ok` – Rqomey Jul 18 '13 at 10:15

5 Answers5

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.)

Fredrik
  • 940
  • 4
  • 10
  • Thanks,This seems to be exactly it! – Rqomey Jul 23 '13 at 07:35
  • Sorry, would you mid explaining what you mean by main event loop? The program scans a web page every minute. – Rqomey Jul 23 '13 at 09:31
  • 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. – Fredrik Jul 23 '13 at 09:48
  • Ahh yea. That makes wayyy more sense. Thanks! – Rqomey Jul 23 '13 at 11:20
0

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

Imirak
  • 1,323
  • 11
  • 21
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • 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? Thanks – Rqomey Jul 18 '13 at 10:04
  • It has to be running _before_ you open the dialog, since opening the dialog blocks until the dialog is dismissed. – Bryan Oakley Jul 18 '13 at 10:43
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:
    # ...
BenMorel
  • 34,448
  • 50
  • 182
  • 322
A. Rodas
  • 20,171
  • 8
  • 62
  • 72
  • 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) – Rqomey Jul 23 '13 at 07:38
  • 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. – Fredrik Jul 23 '13 at 09:52
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()
ChaosPredictor
  • 3,777
  • 1
  • 36
  • 46
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()
mnille
  • 1,328
  • 4
  • 16
  • 20