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).
#1
The original question I had was about making a Tkinter label display the time, here. The reply [below, in code] that helped me with my problem, also provided me more problems. After two months of attempting to find an answer, here I am. So...

import time
import tkinter as tk
 
APP_TITLE = "The Time"
 
APP_XPOS = 100
APP_YPOS = 100
APP_WIDTH = 200
APP_HEIGHT = 100
 
 
class Application(object):
 
    def __init__(self, main_win):
        self.main_win = main_win
         
        self.time_var = tk.StringVar()
        self.build()
         
    def build(self):
        tk.Label(self.main_win, textvariable=self.time_var, width=10, fg='blue',
            font=('Helvetica', 30, 'bold')).pack(expand=True)
             
        self.update_time()
         
    def update_time(self):
        self.time_var.set(time.strftime('%H:%M:%S'))
        self.main_win.after(1000, self.update_time)
                
def main():
    main_win = tk.Tk()
    main_win.title(APP_TITLE)
    #main_win.geometry("+{}+{}".format(APP_XPOS, APP_YPOS))
    main_win.geometry("{}x{}".format(APP_WIDTH, APP_HEIGHT))
     
    app = Application(main_win)
     
    main_win.mainloop()
Particularly, the part where "main_win" is both a part of the application class, and part of a function definition? What is going on here? Searches related to classes and variables always seem to give me tutorials on OOP, class inheritance, class variables, or whatever but not this particular problem.

class Application(object):
     def __init__(self, main_win):   # this line
        self.main_win = main_win     # and this line

def main():
    main_win = tk.Tk()               # combined with this line
    app = Application(main_win)      # and this line, confuse me
    main_win.mainloop()
The __init__ method's "self.main_win = main_win" confuses me, and when "main_win" is an argument of the init method it confuses me more... Especially when it is also an instance of the Tk() class?

Thank you for your time.
Reply
#2
If written this way, may be easier to understand
has default values for title, width, height, xpos and ypos
** Note ** Uses f-string which requires python 3.6 or newer.
In example title default is overridden.
import time
import tkinter as tk
    
  
class Application(object):
    """
        Initialization with default values for title, width, height, xpos, ypos
        any of which can be overidden.

        Uses f-string which requires python 3.6 or newer.
    """
    def __init__(self, parent, title='Application', width=200, height=100, xpos=200, ypos=200):
        self.parent = parent

        self.parent.title(title)
        self.parent.geometry(f"{width}x{height}+{xpos}+{ypos}")

        self.time_var = tk.StringVar()
        self.build()
          
    def build(self):
        tk.Label(self.parent, textvariable=self.time_var, width=10, fg='blue',
            font=('Helvetica', 30, 'bold')).pack(expand=True)
              
        self.update_time()
          
    def update_time(self):
        self.time_var.set(time.strftime('%H:%M:%S'))
        self.parent.after(1000, self.update_time)


def main():
    # Create an instance of Tk named main_win
    main_win = tk.Tk()
    #override default title
    title='The Time'
    # create instance of Application (with initialization variables)      
    app = Application(main_win)

    # standard tkinter mainloop      
    main_win.mainloop()


if __name__ == '__main__':
    main()
Reply
#3
Question about this part... (pseudo-code):

class IsntImportant(Object):
    def __init__(self, parent):
        self.parent = parent
Specifically lines 2 and 3, if it were not clear. 100% not sarcastic, just new and learning this stuff, and don't want to try and attempt to look like I know what I'm doing, because I don't. But some times attempting to explain what I think is going on can help me understand it...

Anyway, is this essentially saying something like, "when you create an instance of this class, give it a variable called 'parent' [or rather, 'nameOfInstancedThing_parent' behind the scenes], and set it equal to whatever was passed in upon creation"? Would a variable equal to that class in the example above, without a parent value assigned to it, default to "None" or throw an error?

Also (and in relation to Tk), would it be correct to say that if you have another instanced object of the same "Tk() type", with parent set to "None" by default, that this is how "pop-up" menus are constructed? A sub-class of the "Tk() class" whose value of the parent variable is "None" but still part of the program?

Thank you!
Reply
#4
written this way: def __init__(self, parent):
you must pass a value for parent when instantiating __init__(self, parent):.
if you write it like __init__(self, parent=None):
then parent is optional when creating an instance of __init__(self, parent):
example with default parent == 'woogie':
class IsntImportant(Object):
    def __init__(self, parent='woogie'):
        self.parent = parent

myclass = IsntImportant() # parent defaults to 'woogie'

myotherclass = IsntImportant(parent='main_win') # parent changed to 'main_win'
Reply
#5
Okay, so simply indenting code doesn't just magically change things into classes. I am now getting errors related to the __init__ method when attempting to insert code into the build() method(?) of the class for the Application. I guess I am having trouble understanding how the interactions between objects within the class works, or how channels of communication between widgets happen, based on some init method. I do have a working "partial" program in tkinter, which (as a demonstration of functionality) switches between a label and an entry widget based on what radio button is selected. The interaction between widgets being the variables that control their "logic" functions; ie, "When I click on this, it changes this." So I am understanding some of it.

But that was all done by just importing everything. "from tkinter import *" and then just working with it in the module as is, without classes. That doesn't seem to work now.

Do I need a build method for every widget?
And, for every widget that has a build method, has a counterpart in the init method which calls the corresponding build method?
And that "master init method" in the Application class holds the default values for each build method?

If all that is true, then I should see an increase of code in my "Application", and the "main()" wouldn't change at all?
Reply
#6
Quote:Okay, so simply indenting code doesn't just magically change things into classes. I am now getting errors related to the __init__ method when attempting to insert code into the build() method(?) of the class for the Application.
An example please.
Reply
#7
Sorry, no example can be provided. It was a bad line of questions on my part.

I am trying to understand the process by which widgets are added to the GUI using classes in this manner. Each widget will be fairly unique to each part of the GUI, and it seems that each frame will have its own __init__ method? Is the indentation level of each widget in the code, what determines which frame that widget belongs to? And how would frames within frames be handled? Or would one big build() method be the body of the program which places all the widgets on the screen? Can I just assign a variable as an object within an object, of a widget I want to display?

I don't have examples, because I don't know what to code. What goes where? Helps to know internals and stuff, and I'm not quite sure I understand all of that yet either, but still learning. Thank you very much for being patient with me, you've been answering all my questions just fine.
Reply
#8
Quote:I am trying to understand the process by which widgets are added to the GUI using classes in this manner.
You really should spend some time learning about classes in general.
a widget is a class as a matter of fact everything in python is a class
To show this, consider this example:
>>> a = 5
>>> type(a)
<class 'int'>
>>>
a is an instance of class int
as for widgets:
>>> import tkinter
>>> root = tkinter.Tk()
>>> type(root)
<class 'tkinter.Tk'>
>>> label_a = tkinter.Label(text='abc')
>>> type(label_a)
<class 'tkinter.Label'>
>>> # If you want to see methods and attributes for Label:
>>> help(tkinter.Label)
...
here are some tutorials on classes:
Class Basics
Class Intermediate: Inheritance
Class Intermediate: Operator Overloading
Classes [advanced]: Dependent attributes (and Descriptors)
Classes [advanced]: Descriptors (managed attributes)
Reply
#9
(Mar-22-2019, 09:05 PM)Ceegen Wrote: what determines which frame that widget belongs to?
when a widget is created it is passed a parent, the created widgets __init__ method then set the passed in widget as it parent, the widget then belongs to the passed in parent.
Reply
#10
(Mar-22-2019, 11:33 PM)Larz60+ Wrote:
Quote:I am trying to understand the process by which widgets are added to the GUI using classes in this manner.
You really should spend some time learning about classes in general.
a widget is a class as a matter of fact everything in python is a class
To show this, consider this example:
>>> a = 5
>>> type(a)
<class 'int'>
>>>
a is an instance of class int
as for widgets:
>>> import tkinter
>>> root = tkinter.Tk()
>>> type(root)
<class 'tkinter.Tk'>
>>> label_a = tkinter.Label(text='abc')
>>> type(label_a)
<class 'tkinter.Label'>
>>> # If you want to see methods and attributes for Label:
>>> help(tkinter.Label)
...
here are some tutorials on classes:
Class Basics
Class Intermediate: Inheritance
Class Intermediate: Operator Overloading
Classes [advanced]: Dependent attributes (and Descriptors)
Classes [advanced]: Descriptors (managed attributes)

Reading up...

Search results for OOP and Python related material is flooded with all sorts of Udemy-related things. The docs don't seem to explain things in a way I can understand it, as most documentation I've seen tries to explain as little as possible.

(Mar-23-2019, 12:16 AM)Yoriz Wrote:
(Mar-22-2019, 09:05 PM)Ceegen Wrote: what determines which frame that widget belongs to?
when a widget is created it is passed a parent, the created widgets __init__ method then set the passed in widget as it parent, the widget then belongs to the passed in parent.

Okay. I'm going to go try a few things now in the code and see if I really understand what you're saying.

If I have any more questions as a result of that, I'll just come back to this thread.


Thanks x2.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Trying to understand classes menator01 7 3,293 Oct-27-2019, 04:26 PM
Last Post: menator01
Question Helping understand classes Miraclefruit 10 6,307 Nov-27-2017, 01:58 PM
Last Post: Windspar
  Using classes? Can I just use classes to structure code? muteboy 5 5,065 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