I am creating a Tkinter/Python3 application where the main window inherits from Notebook
(i need tabs), and each tab should be a custom class inheriting from Frame
(I would then dynamically use matplotlib
to create custom graphs).
Unfortunately I don't seem to be able to have Notebook
accept my custom Frames
.
Following very reduced snippet of code:
#!/usr/bin/env python3
from tkinter import *
from tkinter.ttk import Notebook
class MyFrame1(Frame):
def __init__(self, master=None, mytext=""):
super().__init__(master)
self.create_widgets(mytext)
def create_widgets(self, mytext):
self.label = Label(self.master, text=mytext, anchor=W)
# this is not placed relative to the Frame, but to the
# master
# 1. How I get the relative coordinates inside the frame
# to be 10, 10 of the frame area?
self.label.place(x=10, y=10, width=128, height=24)
class MyNotebook(Notebook):
def __init__(self, master=None):
super().__init__(master)
self.create_widgets()
def create_widgets(self):
self.f1 = MyFrame1(self, "abc")
# once the UI is drawn, the label "def" seems to overlay
# "abc" even when "f1" is selected
# 2. Why is self.f2 always shown even when self.f1 is
# selected?
self.f2 = MyFrame1(self, "def")
self.add(self.f1, text="f1")
self.add(self.f2, text="f2")
# Without this command nothing gets drawn
# 3. Why is this? Is this equivalent of 'pack' but for
# pixel driven layout?
self.place(width=640, height=480)
def main():
root = Tk()
root.minsize(640, 480)
root.geometry("640x480")
app = MyNotebook(master=root)
# this works as intended the label is indeed placed
# in the frame at 10, 10
#app = MyFrame1(master=root, mytext="123abc")
app.mainloop()
return None
if __name__ == "__main__":
main()
As per comments I have the following main question: why aren't my custom instances of MyFrame1
properly displayed inside MyNotebook
?
Sub questions:
- How can I get relative coordinate areas of where the frame is located when
place
my elements (in this case aLabel
)? - Why even when
self.f1
tab is selected in the UI, I can still see the content ofself.f2
tab? - Is
self.place
required in order to show all sub-elements when not usingpack
? - If I dynamically create Tkinter elements after the
MyNotebook
is initialized, will those be bound to respective tabs?
Not sure what I'm doing wrong?
Thanks!
CodePudding user response:
Not sure what I'm doing wrong?
Your create_widgets
method needs to add widgets to self
, not self.master
.
How can I get relative coordinate areas of where the frame is located when place my elements (in this case a Label)?
I don't understand what you mean by this. When you use place
, coordinates will be interpreted relative to the frame. However, I strongly advise against using place
. Both pack
and grid
will trigger the frame to resize to fit its children which almost always results in a more responsive UI
Why even when self.f1 tab is selected in the UI, I can still see the content of self.f2 tab?
Because you added internal widgets to self.master
instead of self
.
Is self.place required in order to show all sub-elements when not using pack?
No. It is required to use a geometry manager but it doesn't have to be place
. Usually, place
is the least desirable geometry manager to use. pack
and grid
are almost always better choices except for some very specific situations.
If I dynamically create Tkinter elements after the MyNotebook is initialized, will those be bound to respective tabs?
They will be in whatever tab you put them in.
Finally, I would suggest that you remove self.place
in create_widgets
. Instead, call pack
, place
, or grid
in the same block of code that creates an instance of that class.
It's a bad practice for a widget to add itself to another widget's layout. The code that creates the widget should be the code that adds the widget to the layout.