thanks for reading:
OBJECTIVE:
I am practicing using OOP, and wanted to create a class with class variables for a label widget I'm creating with tkinter. This way I can create many labels and don't need to specify the same font, font size, colors, etc, for each one.
PROBLEM:
I am unable to figure out how I can call a class instance when it needs to also reference the tkinter method. (Alternatively, should I even be trying to include the tkinter reference when creating a class?)
Here's an example of what I have:
import tkinter as tk
class ui_Labels:
"This class sets the baseline characteristics for the widgets, including font, font size, and colors"
#If I understand correctly, below are called class attributes#
tkLabel = tk.Label
rootRef = uiRoot
varFont = "Calibri"
fontSize = 14
varFG = "f2f2f2"
varBG = "#3b3b3b"
#Constructor
def __init__(self, name, varText):
self.name = name
self.varText = varText
# CLASS OBJECTS
sectionHeader = ui_Labels("Section Header","Magic XML Iterator")
# Attempt to call the instance (not sure if that's the correct phrasing
tk.Label(sectionHeader)
When to call the sectionHeader object as a tk.Label, I get the AttributeError message: "ui_Labels' object has no attribute 'tk'.
It looks like the message is saying that I need to reference the tk method in the class, but I wasn't sure how best to do so.
TL;DR Question:
Does anyone have a suggestion on the best way write a class or its associated object(s) for the purpose of making tkinter Widget templates?
Thank you!
Best,
Chris
CodePudding user response:
You don't want a Label
to be a class attribute. Instead, you need to define the Label
in __init__
. You also need to pass the root/parent as an argument in __init__
so that you can use it to create the label. You can't have it as an attribute as it is not necessarily the same every time, and hasn't been defined in your code regardless.
Essentially what you want is a custom widget that you can create, grid/pack and interract with as a normal widget, but with some custom parameters. A more correct example of how to create a custom widget as a class, using your code, is:
import tkinter as tk
# Your class
class ui_Labels():
'''This class sets the baseline characteristics
for the widgets, including font, font size, and colors
'''
# Attributes
varFont = "Calibri"
fontSize = 14
varFG = "#F2F2F2"
varBG = "#3b3b3b"
# Constructor
def __init__(self, parent, name, varText):
self.parent = parent
self.name = name
self.varText = varText
self.label = tk.Label(
parent,
text = varText,
fg = self.varFG,
bg = self.varBG,
font = (self.varFont, self.fontSize)
)
# Allows you to grid as you would normally
# Can subsitute pack() here or have both class methods
def grid(self, **kwargs):
self.label.grid(kwargs)
# Main GUI
root = tk.Tk()
# Create an instance of your class
sectionHeader = ui_Labels(root, "Section Header","Magic XML Iterator")
sectionHeader.grid(row=1, column=2)
root.mainloop()
CodePudding user response:
I would suggest you to go through some tutorials on Python OOP.
Below is an example of creating a custom label class based on your code:
import tkinter as tk
# custom label class inherited from tk.Label
class ui_Label(tk.Label):
'''
This class sets the baseline characteristics for the widget,
including font, font size and colors
'''
# class attributes
varFont = "Calibri"
fontSize = 14
varFG = "#f2f2f2"
varBG = "#3b3b3b"
# Constructor: added parent argument
def __init__(self, parent, name, varText):
kwargs = {
'text': varText,
'font': (self.varFont, self.fontSize),
'fg': self.varFG,
'bg': self.varBG,
}
# need to call constructor of inherited class
super().__init__(parent, **kwargs)
# I don't know what the purpose of 'name' is
# so just use an instance variable to save it
self.name = name
root = tk.Tk()
# create instance of custom label
sectionHeader = ui_Label(root, "Section Header", "Magic XML Iterator")
sectionHeader.pack()
root.mainloop()