Python Forum
Help me understand this... (Classes and self).
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help me understand this... (Classes and self).
#11
Here are some buttons added to two different frames, 1 button is added inside the class the other is added outside of it.
import tkinter as tk

class MainFrame(tk.Frame):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.pack()
        button = tk.Button(self, text='button1')
        button.pack(side="top")
        
class AnotherFrame(tk.Toplevel):
    def __init__(self, parent=None):
        super().__init__(parent)
        button = tk.Button(self, text='button3')
        button.pack(side="top")


root = tk.Tk()
main_frame = MainFrame(root)
button = tk.Button(main_frame, text='button2')
button.pack(side="top")
another_frame = AnotherFrame(main_frame)
button = tk.Button(another_frame, text='button4')
button.pack(side="top")

root.mainloop()
Reply
#12
(Mar-23-2019, 10:47 PM)Yoriz Wrote: Here are some buttons added to two different frames, 1 button is added inside the class the other is added outside of it.

That helped a lot, actually. Thank you!
Reply
#13
Okay new question, still related to classes and tkinter though:
How do I display the contents of a frame from object A, in another frame from object B?
Example...

import tkinter as tk
import tkinter.ttk as ttk


class MainFrame(tk.Tk):
    '''
    _Target_ for insertion of widgets to display from another frame constructed
    from another class.
    '''

    def __init__(self, parent=None):
        super().__init__(parent)
        self.build_mb()
        self.build_nb()

    def build_mb(self):
        menu_bar = tk.Menu(self)
        self.config(menu=menu_bar)
        options_menu = tk.Menu(menu_bar, tearoff=0)
        menu_bar.add_cascade(label="Options", menu=options_menu)
        options_menu.add_command(label="Quit", command=self.destroy)

    def build_nb(self):
        nb = ttk.Notebook(self)
        nb.grid()
        tab_one = tk.Frame(nb) # <-- target actual # #
        nb.add(tab_one, text='Entries')
        tab_two = tk.Frame(nb)
        nb.add(tab_two, text='Unused')


class TabOne(tk.Frame):
    '''
    _This_ is the frame to display in "tab_one" of the MainFrame object.
    '''

    def __init__(self, parent=None):
        super().__init__(parent)
        self.build_tab()

    def build_tab(self):
        entry = ttk.Entry()
        entry.grid(column=0, row=0)
        submit = ttk.Button(text='Submit')
        submit.grid(column=1, row=0)


def run_main():
    main_nb = MainFrame()
    tab1 = TabOne(main_nb) #This doesn't work; "main_nb.tab_one" (or whatever) throws error.
    main_nb.mainloop()

if __name__ == '__main__':
    run_main()
Is it possible to get the widgets in the frame named tab1 to display in the notebook this way, or must it all be constructed together?
Reply
#14
You need to make
tab_one = tk.Frame(nb) # <-- target actual # #
accessible by adding it as a variable of MainFrame
self.tab_one = tk.Frame(nb) # <-- target actual # #
nb.add(self.tab_one, text='Entries')
then you can use
tab1 = TabOne(main_nb.tab_one) #This doesn't work; "main_nb.tab_one" (or whatever) throws error.
Reply
#15
Okay, so is that how classes instantiate variables for an instance, when an instance of it is created?
Specifically where in the second Python example you said to use "self.tab_one"?

As opposed to my code, which makes it a class variable (correct?) rather than an instantiated variable?
[edit: meaning, my code is attempting to place widgets into a class?]
Is that what I'm doing wrong?
Reply
#16
your code
tab_one = tk.Frame(nb) # <-- target actual # #
is making a new frame who's parent is the notebook that has a pointer to it in the variable nb.
this new frame has a pointer to it stored in tab_one which is a local variable to the method build_tab.
when the method build_tab has done all its code, tab_one will be gone leaving no access to the frame.

by changing it to
self.tab_one = tk.Frame(nb) # <-- target actual # #
tab_one becomes a instance variable, that is accessible from both inside the instance(by other methods) and outside the instance(by the object instance).

Example
class MainFrame:
    def __init__(self):
        self.build_nb()
        
    def build_nb(self):
        tab_one = '<local variable>)'
        self.tab_one = '<instance variable>'
        
        print('printed by MainFrame>build_nb:\n'
              f'tab_one = {tab_one}\n'
              f'self.tab_one = {self.tab_one}\n')
        
    def output_tab_one(self):
        print('printed by MainFrame>output_tab_one:\n'
              f'tab_one = tab_one cannot be accessed its forgotten about\n'
              f'self.tab_one = {self.tab_one}\n')
        

main_frame = MainFrame()
main_frame.output_tab_one()
print('printed by instance of MainFrame:\n'
    f'tab_one = tab_one cannot be accessed its forgotten about\n'
    f'self.tab_one = {main_frame.tab_one}')
Output:
printed by MainFrame>build_nb: tab_one = <local variable>) self.tab_one = <instance variable> printed by MainFrame>output_tab_one: tab_one = tab_one cannot be accessed its forgotten about self.tab_one = <instance variable> printed by instance of MainFrame: tab_one = tab_one cannot be accessed its forgotten about self.tab_one = <instance variable>
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Trying to understand classes menator01 7 3,289 Oct-27-2019, 04:26 PM
Last Post: menator01
Question Helping understand classes Miraclefruit 10 6,306 Nov-27-2017, 01:58 PM
Last Post: Windspar
  Using classes? Can I just use classes to structure code? muteboy 5 5,062 Nov-01-2017, 04:20 PM
Last Post: metulburr

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020