Is there a way to update the tkinter messageboxes live?

Viewed 106

I am trying to make a GUI(using tkinter) for checking the code using test cases. Just like you see in Competitive Programming Websites like Hackerrank , SPOJ , CodeForces etc.

Now I have somehow managed to print in the terminal for what test cases the code failed and for what the code passed.

But the catch is , I want to do the same in tkinter messageboxes.

My code runs in loop , so it checks each and every test cases and then prints out the result immediately rather than storing all the result in a list and checking them in the end.

So I want my Messagebox to also do the same i.e update everytime a test cases has been evaluated and show whether the test case was passed or not?

Is it possible to implement?

2 Answers

If you mean the messagebox module that comes with tkinter, then no. But you can easily make your own message boxes with the Toplevel widget, and those can do anything you want.

As Novel suggested in his answer to create your own messagebox inheriting from tk.Toplevel, Here is a (Not the best) working solution which will serve the purpose that you described.

It inherits from tk.Toplevel class.

Documentation of my messagebox :D

I implemented a method called updateInfo() which can be simply used to update the message and also the title of the window.

Note that the size of window, fonts, colors are always customizable so feel free to add your touch. Here is the implementation:

import tkinter as tk

class MyCrazyBox(tk.Toplevel):
    def __init__(self, title='', message=''):
        tk.Toplevel.__init__(self)
        self.geometry('400x200+200+100') # Must change these accordingly
        self.title(title)
        # set the options according to your needs.
        self.messageLabel = tk.Label(self, text=message,
                                     bg='#fff', fg='#000', font=('roboto', 25))
        self.messageLabel.pack(expand=True, fill=tk.BOTH)

    def updateInfo(self, title='', message=''):
        self.title(title)
        self.messageLabel.configure(text=message)


# To create a new message box just create an instance of the class MyCrazyBox

Both the title and message default to '' - an empty string - if not provided when creating am instance.

All these below examples will work to create a messagebox from class MyCrazyBox.

# 1. MyCrazyBox('Info', 'Loading....') # both title and message provided
# 2. MyCrazyBox(title='test', message='Just a check') 
# 3. BoxVariable = MyCrazyBox('warning', 'Wrong credentials')
# 4. MyCrazyBox('Just the title')
# 5. MyCrazyBox(message='Where is the title, you freak?')

Once you have created a box, you can use that same box to update info as many times as needed with the .updateInfo() method.

Important:: You need to assign the MyCrazyBox instance to a variable if you want to use .updateInfo() method.

like

aBox = MyCrazyBox('Info', 'Loading....')
root.after(4000, lambda: aBox.updateInfo('Info', 'Still Running the test case'))
root.after(5554, lambda: aBox.updateInfo('Congrats', 'Test case Passed'))
# added delay to simulate some process happening

Simply said aBox.updateInfo('Test', 'Just checking') will update the box with the arguments supplied. The argument nature is the same as class instance creation.

Complete example

import tkinter as tk

class MyCrazyBox(tk.Toplevel):
    def __init__(self, title='', message=''):
        tk.Toplevel.__init__(self)
        self.geometry('400x200+200+100') # Must change these accordingly
        self.title(title)
        # set the options according to your needs.
        self.messageLabel = tk.Label(self, text=message,
                                     bg='#fff', fg='#000', font=('roboto', 25))
        self.messageLabel.pack(expand=True, fill=tk.BOTH)

    def updateInfo(self, title='', message=''):
        self.title(title)
        self.messageLabel.configure(text=message)
        
def dosomething():
    aBox = MyCrazyBox('Info', 'Running test case 1..')
    root.after(5000, lambda: aBox.updateInfo('Congrats', 'Test case 1 Passed.'))
    # just to simulate a delay of 5 sec in checking test case
    
root = tk.Tk()
tk.Button(root, text='Do something', command=dosomething).pack()
root.mainloop()
Related