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.

2
  • 1
    Die you read this ? stackoverflow.com/a/17470842 Commented Aug 23, 2020 at 7:21
  • I have now. Spot on, very interesting and helpful. Thank you very much. Commented Aug 23, 2020 at 7:34

1 Answer 1

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()
Sign up to request clarification or add additional context in comments.

3 Comments

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__()
Thank you. This is essentially the ideas detailed in the link provided above by @Atlas435 (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 : thinkingtkinter.sourceforge.net. Excellent reading for beginners.
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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.