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.
Related
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
Is the equivalent of ToggleButton exist in PyGtk ?
I would like to have a callback like: True or False.
self.liste = gtk.ComboBox(self.liststore)
self.liste.connect("changed", self.result_list)
With this method, the program can't detect if the user clicks again on the same choice.
Thanks
I don't have any specific advice as I haven't used ComboBox much, but I'm pretty sure that what you want to do is possible.
The GTK tutorial says
ComboBox uses a TreeModel (usually a ListStore) to provide the list
items to display.
The basic ComboBox methods are great for simple things, but for more advanced usage you need to play with things at the TreeModel level yourself. To do that effectively, you need to know how they work; fortunately the docs in the tutorial are pretty good: TreeView widget, but also check out the info in the reference manual.
To make the equivalent of a toggle button you can use 14.4.8. Activatable Toggle Cells
I have some objects in a PyQt GUI that I wish to be hidden when the program runs until a button is pressed that shows them. So far all my attempts have failed, I have experimented with Signals/Slots but I can't seem to find a way of calling a function without an action (e.g. a button press). I would like to know if it is possible to call hide() on an object in this way, and if so, how.
To Close:
QtCore.QObject.connect(self.closeWidget, QtCore.SIGNAL(_fromUtf8("activated()")), widgetName.close)
To Show:
QtCore.QObject.connect(self.actionShow, QtCore.SIGNAL(_fromUtf8("activated()")), widgetName.show)
In other words, widgets inherit a close() and show() method.
See http://pyqt.sourceforge.net/Docs/PyQt4/qwidget.html
Also, some example code: http://www.saltycrane.com/blog/2007/06/more-pyqt-example-code/
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.
Is there an on-value-change type of event for data input widgets like Entry, Text, Spinner, Checkbutton, Radiobutton? By on-value-change, I mean the ability to detect when the value of a widget has changed due to keyboard input or cut/delete/paste (and Text edit_undo/edit_redo) activity? I see no such event described in the Tkinter event documentation [1].
Is the proper technique to link Tkinter variables to widget values I want to monitor and use these variables' .trace_variable( 'w', ... ) methods to bind to value changes? This seems like the right approach, but I haven't seen a lot of trace_variable() use in the Tkinter application source code that I've studied ... leading me to be cautious about using this approach.
[1] http://infohost.nmt.edu/tcc/help/pubs/tkinter/events.html
Different widgets call for different solutions. For example, check buttons and radio buttons have a command option, and with an entry widget you can use the built-in validation features.
For all the widgets that can be tied to a variable, doing a variable trace is a common solution. The text widget is one exception since you can't associate it with a variable without a lot of effort.
In the tcl/tk world I associate all my widgets to a single array (tcl's name for a hash map / dictionary) and then put a single trace on the array. Unfortunately tkinter doesn't directly support tcl arrays. However, support is somewhat easy to hack in. For more information see my response to this question: How to run a code whenever a Tkinter widget value changes?