I'm trying to make the following code meaningful as much as possible, using inheritance. The purpose is for learning. The App class is the most super class. And the Tabs class has inherited it. Can I make the following code more meaningful and break it for more better classes? Instead of creating notebook = self.notebook for all the Tabs class methods, can't I initialize it in the Tab class's init method. When it is done notebook was non recognizable. I need all the tabs background color to be same. Hence, if I can mention it in the Tabs class's init method and convert its other methods(about, ..., visualize) into child classes of Tabs class, will it be a good suggestion? kindly help
import tkinter as tk
from tkinter import ttk
from PIL import Image, ImageTk
from tkinter.filedialog import askopenfile
from tkinter.font import Font
class App(tk.Tk):
def __init__(self):
super().__init__()
# intializing the window
self.title("Data Visualization")
# configuring size of the window
self.geometry('800x650')
# this removes the maximize button
self.resizable(0,0)
# Styling the tabs
s = ttk.Style()
s.theme_create('pastel', settings={
".": {
"configure": {
"background": '#ffffff', # All except tabs
"font": 'red'
}
},
"TNotebook": {
"configure": {
"background":'#848a98', # Your margin color
"tabmargins": [5, 5, 4, 4], # margins: left, top, right, separator
}
},
"TNotebook.Tab": {
"configure": {
"background": '#d9ffcc', # tab color when not selected
"padding": [10, 2], # [space between text and horizontal tab-button border, space between text and vertical tab_button border]
"font":"white"
},
"map": {
"background": [("selected", '#ccffff')], # Tab color when selected
"expand": [("selected", [1, 1, 1, 0])] # text margins
}
}
})
s.theme_use('pastel')
#s.theme_use('default')
s.configure('TNotebook.Tab', font=('URW Gothic L','13','bold'))
#s.map("TNotebook", background= [("selected", "#ffffff")])
#Create Tab Control
self.notebook = ttk.Notebook(self)
class Tabs(App):
def __init__(self):
super().__init__()
def about(self):
my_font = Font(
family = 'Arial',
size = 15,
weight = 'bold',
slant = 'roman',
underline = 0,
overstrike = 0
)
my_font2 = Font(
family = 'Arial',
size = 11,
#weight = 'bold',
slant = 'roman',
underline = 0,
overstrike = 0
)
notebook = self.notebook
f1 = tk.Frame(notebook)#,background="#FFFAF0")
#logo
logo = Image.open('airport.jpg')
#Resize the Image using resize method
resized_image= logo.resize((600,300), Image.ANTIALIAS)
logo = ImageTk.PhotoImage(resized_image)
logo_label = ttk.Label(f1,image=logo,relief="raised")
logo_label.image = logo
#logo_label.grid(column=3, row=0)
logo_label.place(relx=0.12,rely=0.1) # using place
notebook.add(f1, text="About" )
# Tab1
ttk.Label(f1, text="Airports, Airport-frequencies and Runways analysis", font=my_font).place(relx=0.2,rely=0.03)
#text box
text_box = tk.Text(f1, height =10,font=my_font2)
text_box.insert(1.0,"""This application allows you to analyze Airports, Airport-frequencies and Runways of Europe.
• Tab "Load and Save Actions" is to load the initial data set (which consists of three CSV files) and translate it into a suitable format. \n\n• Tab "Preprocess" is to clean and prepare the initial data set, managing inconsistences, \nerrors, missing values and any specific changes required. \n\n• Tab "Visualize" is to use the prepared data set to generate output and visualisations.""" )
text_box.tag_configure("center", justify="center")
text_box.tag_add("center", 1.0, "end")
text_box.place(relx=0.1, rely=0.65)
text_box.config(highlightthickness = 2, borderwidth=0,background='#FFFAFA')
notebook.pack(expand=1, fill="both")
def load_save(self):
notebook = self.notebook
f2 = tk.Frame(notebook,background="#ffffff")
notebook.add(f2, text="Load and Save Actions" )
def preprocess(self):
notebook = self.notebook
f3 = tk.Frame(notebook,background="#ffffff")
notebook.add(f3, text="Preprocess" )
def visualize(self):
notebook = self.notebook
f4 = tk.Frame(notebook,background="#ffffff")
notebook.add(f4, text="Visualize" )
if __name__ == "__main__":
tabs=Tabs()
tabs.about()
tabs.load_save()
tabs.preprocess()
tabs.visualize()
tabs.mainloop()
-
\$\begingroup\$ Please edit your question so that the title describes the purpose of the code, rather than its mechanism. We really need to understand the motivational context to give good reviews. Thanks! \$\endgroup\$Toby Speight– Toby Speight2022年04月22日 21:17:19 +00:00Commented Apr 22, 2022 at 21:17
1 Answer 1
meaningful as much as possible, using inheritance
Inheritance basically has no place here. Eventually, if your tab sections are larger and share more common elements, then perhaps having a Tab
superclass would make sense, but it should absolutely not inherit from App
.
Can I make the following code more meaningful and break it for more better classes?
I have no idea what that means, but you'll either want one single class, or perhaps eventually one class per tab.
Otherwise:
Don't inherit from Tk
; instantiate it (has-a, not is-a).
In a few places you've passed 0 where you should pass False
. A mature IDE like PyCharm, or probably a type-checking tool like mypy, will tell you this. This includes the call to resizable
.
Long, constant literals such as your style dictionary may be better-suited to values in effectively static scope.
Methods such as about
should be
- called by your constructor, not by the instantiating code;
- named perhaps
_make_preprocess
or_setup_preprocess
- notpreprocess
- since this isn't doing the preprocessing - marked private via leading underscore; and
- type-hinted as returning
None
.
You know about tk's ability to process named colours like white
, since you've used that - so why would you also be passing #ffffff
? Prefer the former.
Some of your comments, such as # tab color when not selected
, are fine since they're describing something non-obvious. Most others need to be deleted, particularly those like:
logo_label.place() # using place
f2
is a bad name for at least two reasons. First, it's meaningless and should include the word "frame". Second: this method should work and make sense regardless of whether the frame is actually the second frame. The notebook does not need an index for its add
call. So just call it frame
.
Similarly, don't say my_font
; this is actually the label_font
.
I do not have your airport.jpg
so for illustrative purposes I have substituted my own.
Suggested
import tkinter as tk
from tkinter import ttk
from PIL import Image, ImageTk
from tkinter.font import Font
class App:
TAB_SETTINGS = {
'.': {
'configure': {
'background': 'white', # All except tabs
'font': 'red'
}
},
'TNotebook': {
'configure': {
'background': '#848a98', # Your margin color
'tabmargins': [5, 5, 4, 4], # margins: left, top, right, separator
}
},
'TNotebook.Tab': {
'configure': {
'background': '#d9ffcc', # tab color when not selected
'padding': [10, 2],
# space between text and horizontal tab-button border, space between text and vertical tab_button border
'font': 'white'
},
'map': {
'background': [('selected', '#ccffff')], # Tab color when selected
'expand': [('selected', [1, 1, 1, 0])] # text margins
}
}
}
def __init__(self) -> None:
root = self.root = tk.Tk()
root.title('Data Visualization')
root.geometry('800x650')
# this removes the maximize button
root.resizable(False, False)
s = ttk.Style()
s.theme_create('pastel', settings=self.TAB_SETTINGS)
s.theme_use('pastel')
s.configure('TNotebook.Tab', font=('URW Gothic L', '13', 'bold'))
self.notebook = ttk.Notebook(root)
self._make_about()
self._make_load_save()
self._make_preprocess()
self._make_visualise()
self.run = root.mainloop
def _make_about(self) -> None:
label_font = Font(
family='Arial',
size=15,
weight='bold',
slant='roman',
underline=False,
overstrike=False,
)
textbox_font = Font(
family='Arial',
size=11,
slant='roman',
underline=False,
overstrike=False,
)
frame = tk.Frame(self.notebook)
logo = Image.open('airplane.png')
resized_image = logo.resize((600, 300), Image.ANTIALIAS)
logo = ImageTk.PhotoImage(resized_image)
logo_label = ttk.Label(frame, image=logo, relief='raised')
logo_label.image = logo
logo_label.place(relx=0.12, rely=0.1)
self.notebook.add(frame, text='About')
ttk.Label(
frame,
text='Airports, Airport-frequencies and Runways analysis',
font=label_font,
).place(relx=0.2, rely=0.03)
text_box = tk.Text(frame, height=10, font=textbox_font)
text_box.insert(1.0, '''This application allows you to analyze Airports, Airport-frequencies and Runways of Europe.
• Tab "Load and Save Actions" is to load the initial data set (which consists of three CSV files) and translate it into a suitable format.
• Tab "Preprocess" is to clean and prepare the initial data set, managing inconsistences,
errors, missing values and any specific changes required.
• Tab "Visualize" is to use the prepared data set to generate output and visualisations.''')
text_box.tag_configure('center', justify='center')
text_box.tag_add('center', 1.0, 'end')
text_box.place(relx=0.1, rely=0.65)
text_box.config(highlightthickness=2, borderwidth=0, background='#FFFAFA')
self.notebook.pack(expand=1, fill='both')
def _make_load_save(self) -> None:
frame = tk.Frame(self.notebook, background='white')
self.notebook.add(frame, text='Load and Save Actions')
def _make_preprocess(self) -> None:
frame = tk.Frame(self.notebook, background='white')
self.notebook.add(frame, text='Preprocess')
def _make_visualise(self) -> None:
frame = tk.Frame(self.notebook, background='white')
self.notebook.add(frame, text='Visualize')
if __name__ == '__main__':
app = App()
app.run()
Output
-
\$\begingroup\$ Thank u vary much Reinderien.... Very useful insights \$\endgroup\$Hiru– Hiru2022年04月23日 07:15:11 +00:00Commented Apr 23, 2022 at 7:15