what are some of the things within this tkinter program? [duplicate] - python

I want to understand what the below code means:
class PageOne(tk.Frame):
def __init__(self, parent, controller):
What are self, parent and controller? What is the role and scope of these tools here?
I believe self is similar to this in Java, but what's the use of parent and controller?
Later in the code flow I can see:
button1 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
There is a function already defined called show_frame, but why is the controller being used to call this function?

Roughly speaking, the original code1 attempted to use a pseudo-MVC (model, view and controller) architecture. Though without the "model" part -- there was just a "view" (some frames) and a "controller" (the main application). Hence, the reference to a controller object. The original code was actually written to show how to "stack" frames, so it's MVC implementation is very shallow and under-documented since that wasn't the point of the example.
To answer your specific questions:
self represents the current object. This is a common first parameter for any method of a class. As you suggested, it's similar to Java's this.
parent represents a widget to act as the parent of the current object. All widgets in tkinter except the root window require a parent (sometimes also called a master)
controller represents some other object that is designed to act as a common point of interaction for several pages of widgets. It is an attempt to decouple the pages. That is to say, each page doesn't need to know about the other pages. If it wants to interact with another page, such as causing it to be visible, it can ask the controller to make it visible.
You asked "There is a function already defined called show_frame, but why is the controller being used to call this function?" Notice that show_frame is defined in a separate class, in this case the main program class. It is not defined in the other classes. For the other classes to be able to call it, they must call it on an instance of the main class. That instance is named controller in the context of these other classes.
1 Note: even though you likely found the original code in an online tutorial, it originally came from this stackoverflow answer: Switch between two frames in tkinter

Related

Understanding Python Syntax / Notation

Coming from a C++ background, I'm having a little bit of difficulty understanding Python in some situations. For instance, in a GUI app using Tkinter, you might have:
button = Button (master, option=value, ...)
I know what the code is doing (creating a Button object), but I'm trying to figure out the exact details. I'm guessing that button is becoming a pointer to a Button object, and Button (master, option=value, ...) is a call to the constructor, but its hard to see, since I am used to explicit data types and the new operator. My guess could be entirely off though.
I went through several guides and documents on this prior to this question, but just stumbled across the answer here:
"To create a pushbutton in a top-level window or frame named parent:
w = tk.Button(parent, option=value, ...)
The constructor returns the new Button widget."
So it seems to be just a normal object (non-pointer) and the constructor returns a Button object to it.

tkinter Model-View-Controller: deeply-nested widgets calling the controller

I'm refactoring a tkinter GUI along a MVC design pattern. The Controller module imports a View class, and the View class makes requests to the Controller. I have a few ways of registering a change to an entry widget (StringVar trace, binding, etc.), but what if the widget is deeply nested and the callback is at a much higher level? What is the best way to have a request propagate upwards? For example, what if the View has a Frame that has a Frame that has a Widget that changes status?
The two solutions that occur to me are:
Russian Doll approach: Every inner layer is instantiated with either a reference to the View or the Controller, so the widget can directly make a request (e.g. to ViewReference.call_controller(input), or ControllerAlias.request(input). This leaves a trail of breadcrumbs from View to widget.
Family Tree approach: recursively call the parents and ask if they have an "ask controller to do thing" method. If not, ask their parents. This seems more fragile and awkward.

Understanding parent and controller in Tkinter __init__

I want to understand what the below code means:
class PageOne(tk.Frame):
def __init__(self, parent, controller):
What are self, parent and controller? What is the role and scope of these tools here?
I believe self is similar to this in Java, but what's the use of parent and controller?
Later in the code flow I can see:
button1 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
There is a function already defined called show_frame, but why is the controller being used to call this function?
Roughly speaking, the original code1 attempted to use a pseudo-MVC (model, view and controller) architecture. Though without the "model" part -- there was just a "view" (some frames) and a "controller" (the main application). Hence, the reference to a controller object. The original code was actually written to show how to "stack" frames, so it's MVC implementation is very shallow and under-documented since that wasn't the point of the example.
To answer your specific questions:
self represents the current object. This is a common first parameter for any method of a class. As you suggested, it's similar to Java's this.
parent represents a widget to act as the parent of the current object. All widgets in tkinter except the root window require a parent (sometimes also called a master)
controller represents some other object that is designed to act as a common point of interaction for several pages of widgets. It is an attempt to decouple the pages. That is to say, each page doesn't need to know about the other pages. If it wants to interact with another page, such as causing it to be visible, it can ask the controller to make it visible.
You asked "There is a function already defined called show_frame, but why is the controller being used to call this function?" Notice that show_frame is defined in a separate class, in this case the main program class. It is not defined in the other classes. For the other classes to be able to call it, they must call it on an instance of the main class. That instance is named controller in the context of these other classes.
1 Note: even though you likely found the original code in an online tutorial, it originally came from this stackoverflow answer: Switch between two frames in tkinter

PyQt4 Regarding Class Documentation

I'm not sure if this question has been asked before or not, but I have searched for it a bunch, perhaps I'm using the wrong keywords. I've also googled for it, but I think I'd like a more specific answer.
My question relates to the following line seen in pretty much every PyQt4 class documentation
The parent argument, if not None, causes self to be owned by Qt
instead of PyQt.
Constructs a dialog with parent parent.
A dialog is always a top-level widget, but if it has a parent, its
default location is centered on top of the parent. It will also share
the parent's taskbar entry.
I want to understand exactly what this means. From what I understand it has to do with how the object lives in memory and how it interacts with Python's garbage collection.
To be a little bit more concrete, say I have a QMainWindow and I pass it as the parent to a QDialog. ie somewhere I have a function like this
def ShowFooDialog():
dlg = FooDialog()
if dlg.exec_():
--doSomeStuff--
what would be the difference between that and the following
def ShowFooDialog():
dlg = FooDialog(parent=MyMainWindow)
if dlg.exec_():
--doSomeStuff--
Thanks! If this is something that could have been found out by better reading of the PyQt4 docs I apologize in advance!

python widget creation using self on button

I was hoping some one could explain to me the difference and reason behind why I keep coming across two different methods for which people place buttons into the widget? I sometimes see
button = Button('Button', self)
or
self.spinner = QtGui.QSpinBox()
I just want to know whats the difference, is one more beneficial than the other? When to use which in what scenarios and why? Does the position of 'self' affect this in the widget some how?
Assuming you only care about PyQt and PySide…
There are two different places that self appears in your examples, which mean very different things.
First, as an argument to the constructor:
Every widget's constructor has a parent parameter, with a default value of None.
There are three reasons to leave out the parent:
You're going to assign the widget to a layout or other parent after creation.
You're creating a top-level window.
You're creating a special-purpose widget like QDesktopWidget.
If none of these are true, you need to pass a parent. If self is a widget, and the thing you're creating is a child of that widget, you will pass self as the parent.
Here's an example of the first alternative:
self.spinner = QtGui.QSpinBox()
hbox = Qt.QHBoxLayout()
hbox.addWidget(self.spinner)
self.addLayout(hbox)
We can't pass a parent to QSpinBox at construction time because its parent doesn't exist yet. So, we leave it off, and addWidget it to a layout object later.
This is all explained early in most tutorials for PySide or PyQt, like First programs in PySide and Layout management in PySide.
Meanwhile, one of your examples stores the widget in self.spinner, making it an instance attribute on self, which means we can refer to it later. For example, if some other method (like the signal handler for a button) wants to adjust the spinner's value, it can access it as self.spinner.
If you will never need to refer to the child widget in your code after the current function, you don't need to store it.
This part is explained in the Classes chapter in the Python tutorial.

Categories

Resources