Search code examples
pythontkintereventsmodule

tkinter button in imported module: how to update the main module window


I've been finding this difficult to research because I don't know what this process is called. Btw, I'm picking this up in my spare time, not trained in computer science, though I have created small multi-threaded OO applications with event handlers in another language, java, in the past.

EDIT - I've replaced the example code with two example modules, see below.

Context

I have a tkinter application where the main module creates its own window and then from that GUI the user can create extra secondary windows which contain controls that affect the operation of the main module. So far so good, I've got it all working in a large single python file, creating several secondary windows all from within the same module. Motivation: to make it simpler to manage I want to split it into modules in separate files.

The problem (I think)

When tkinter applications are organised into modules the code in the secondary module no longer has visibility of that in the main module, or of objects created there such as the main application tkinter window.

Detailed objective

Just as an example, how can I arrange that when a button is pressed in a secondary window that it can have an effect on the code in the main module/(or even code buried in the main window class in that module). What is the right language in python to describe this?

EDIT:

In the following example the outcome of the button press remains within second_module. I want it to propagate as an event so that any code in the main module or, its window class, can be aware of it, hence the dummy method "well_anything_really()".

Once again, whilst a specific solution would be welcome what I want in the long run is to understand the terminology for this relationship between objects (including tkinter objects) so that I can look it up myself. It makes sense to me to break up the code into modules though I've seen nothing on the web about how to go about this, this seems really odd as it appears fundamental, so I assume I'm simply not looking for the right phrases.

main_module.py:

import tkinter as tk
import second_module

class Application(tk.Frame):                  
    def __init__(self, master=None):
        super().__init__(master)
        master.title("Main window")
        
        second_module.create_secondary_window(tk.Tk())
    
    def well_anything_really(self):
        # I want to make any code here benefit from awareness 
        # of the button press in the secondary window
        print("something dependent on that button press")

root = tk.Tk()
root.geometry("500x200")    
app = Application(master=root) 
app.mainloop()              

second_module.py:

import tkinter as tk

def create_secondary_window(win0):
    win0.title("Secondary window")
        
    button1 = tk.Button(win0,text="Test_button", command=button_response) 
    button1.grid(column=0,row=0)

        
def button_response():        
    print("\nButton response: just a placeholder for any event in the secondary window")
    

Solution

  • You can pass the function well_anything_really to create_secondary_window() as an argument and use this function as the value of command option of the button created in create_secondary_window():

    class Application(tk.Frame):
        def __init__(self, master=None):
            ...
            second_module.create_secondary_window(self, self.well_anything_really)
        ...
    
    second_module.py
    import tkinter as tk
    
    def create_secondary_window(parent, callback):
        win0 = tk.Toplevel(parent)
        win0.title("Secondary window")
    
        button1 = tk.Button(win0, text="Test_button", command=callback)
        button1.grid(column=0, row=0)