WinEunuuchs2Unix
WinEunuuchs2Unix

Reputation: 1949

Python Tkinter Avoid using "root" name in lower level function

Inspired by this 300+ vote closed Q&A: Best way to structure a tkinter application?, I'm looking to avoid explicitly using root in a function within a class. I think it should be implicitly declared through self or parent or something like that. Here is the code in question:

I have this code...

        self.label_this = tk.StringVar()
        self.label_last = tk.StringVar()
        self.label_total = tk.StringVar()

        tk.Label(count_frame, textvariable=self.label_this, \
                 font=(None, MON_FONTSIZE)).pack(anchor=tk.W)
        tk.Label(count_frame, textvariable=self.label_last, \
                 font=(None, MON_FONTSIZE)).pack(anchor=tk.W)
        tk.Label(count_frame, textvariable=self.label_total, \
                 font=(None, MON_FONTSIZE)).pack(anchor=tk.W)
        self.update_cnt_labels()

Then later on...

        ''' Get list of Window ID's on monitor now '''
        new_windows = self.windows_on_monitor(new_windows)
        new_windows_cnt = len(new_windows) / WIN_CNT
        if self.old_windows_cnt == new_windows_cnt :
            FlashMessage (self.label_this, "No new windows to remove...", \
                          3, 750, 250)
            self.update_cnt_labels()
            return

Then later on...

class FlashMessage:
    def __init__(self, widget, message, count=5, on=500, off=300):

        self.delay_show (1, widget, message)
        for i in range(count):
            self.delay_show (on, widget, "")
            self.delay_show (off, widget, message)

    def delay_show(self, ms, widget, message):
        root.after(ms, widget.set(message))
        root.update_idletasks()

I want to avoid using root in the last two lines and use self or something similar.

My program call chain is something like:

Each class and function has haphazard self, positional parameters, *args and **kwargs which mostly serve no purpose. Indeed even the __init__ above might be unnecessary. This is a result of copying code all over stack overflow.

Every second word in the program seems to be self but the word parent is only used in the class ResizingCanvas(). Do I have to propagate parent down the call list and use it somehow?

Upvotes: 0

Views: 68

Answers (1)

Bryan Oakley
Bryan Oakley

Reputation: 385980

You can call after and update_idletasks on any widget. There are many such functions that can be called on any widget but which have a global effect.

In your case, you'll need to pass some widget into the FlashMessage constructor and save the reference. You can then use the reference to call the functions.

You're passing something called widget that doesn't actually contain a widget. You need to rename it to something more appropriate (eg: var), and then pass in an actual widget.

(Note: you also are calling after incorrectly, which I've fixed in the following example)

For example:

class FlashMessage:
    def __init__(self, widget, var, message, count=5, on=500, off=300):
        self.widget = widget
        ...

def delay_show(self, ...):
    self.widget.after(ms, var.set, message)
    self.widget.update_idletasks()

Then, whenever you create an instance of FlashMessage you need to add a widget as the first parameter.

For example, assuming that count_frame is defined in the context where you create an instance of FlashMessage and it is an actual widget, it might look something like this:

if self.old_windows_cnt == new_windows_cnt :
    FlashMessage (count_frame, self.label_this, "No new windows to remove...", \
                  3, 750, 250)
    self.update_cnt_labels()
    return

Upvotes: 1

Related Questions