0

I'm a bit stumped with the proper way to design with Tkinter. I've read dozens of Tkinter examples but since most of them describe simple and specific cases I'm having trouble with finding the right global design for my script. I'm trying to separate as much as possible the GUI code from the data model (I'm working on a very simple card game).

My main problem is how to access Tkinter elements globally, from different functions and classes. Currently I am building the entire interface inside a large gui_build() function, right after the definitions for my data classes. This function is called from a main() function along with all the data initialisation stuff. Problem is, even if I return the Tk root object from gui_build() so that main() can pass it around, I'm having trouble accessing Tk elements when needed.

For example, I have several callback functions for different Tk buttons which are in the global scope. If one of those needs to check the state of a radio button, it's apparently impossible to find it in the Tk root hierarchy by name, and passing references to radio buttons all over the place seems very inelegant.

I can sort of make it work by declaring radio buttons globally but this defeats the purpose of keeping all the GUI code in the same place.

Wondering what could be considered as a "best practice" before trying to reinvent the wheel.

Thank you.

Cirrocumulus
  • 520
  • 3
  • 15

1 Answers1

3

I have been making Tkinter interfaces for 2 years, now. I was facing the same problem initially. From my experience I would suggest that you define a class which inherits Tk root widget and then assign you element widgets as attributes of that class, also the callback functions as functions of that class. That will make accessing global widgets(button) and functions easy. These widgets and functions are global inside the class definition. It makes them easy to access. You can follow following template

from tkinter import *

class Interface(Tk):
    def __init__(self, title):
        Tk.__init__(self)
        self.title(title)
        self.build()
    
    def build(self):
        self.UserNameLabel = Label(self, text="User Name")
        self.UserNameLabel.grid(row=0, column=0, sticky=E, pady=10)
        
        self.UserNameEntry = Entry(self)
        self.UserNameEntry.grid(row=0, column=1, sticky=W, pady=10)
        
        self.PassWordLabel = Label(self, text="Password")
        self.PassWordLabel.grid(row=1, column=0, sticky=E, pady=10)
        
        self.PassWordEntry = Entry(self, show='*')
        self.PassWordEntry.grid(row=1, column=1, sticky=W, pady=10)
        
        self.status = Label(self, text='Please enter User Name and Password')
        self.status.grid(row=2, column=0, columnspan=2, pady=10)
        
        self.LoginButton = Button(self, text='Login', width=20, command=self.checkCreadentials)
        self.LoginButton.grid(row=3, column=0, columnspan=2, pady=10)
    
    def checkCreadentials(self):
        if (self.UserNameEntry.get().strip() == 'username') and (self.PassWordEntry.get()=='password'):
            self.status['text']= 'Welcome !'
        else:
            self.status['text']= 'Invalid User Name or Password!!!'
            self.bell()
        
Interface('Login').mainloop()
Kuldip Chaudhari
  • 1,112
  • 4
  • 8
  • 1
    I do it like this but I dont use wildcard import, I import it as tk and instead of Tk.__init__(self) I use super.__init__() – Thingamabobs Aug 23 '20 at 08:43
  • 1
    Thank you. This is essentially the ideas detailed in the link provided above by @Atlas435 (http://stackoverflow.com/a/17470842). That discussion also mentions a very valuable and easy to follow document explaining the principles behind building the Tk application inside a class : http://thinkingtkinter.sourceforge.net. Excellent reading for beginners. – Cirrocumulus Aug 23 '20 at 08:58
  • Yeah I read, that. @Atlas435 Yes, We should not do wildcard import in case we are using other modules as there is chance that the Names might conflict, Here I have used it to avoid writing a lot of **tk's** – Kuldip Chaudhari Aug 23 '20 at 10:25