File: callbacks.html

package info (click to toggle)
kiwi 1.9.22-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd, squeeze, wheezy
  • size: 11,912 kB
  • ctags: 5,549
  • sloc: python: 15,779; ansic: 193; xml: 77; makefile: 57; sh: 18
file content (280 lines) | stat: -rw-r--r-- 11,220 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="howto.css" type='text/css' />
<link rel="first" href="howto.html" title='Developing applications with Kiwi' />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="node14.html" />
<link rel="prev" href="node10.html" />
<link rel="parent" href="person.html" />
<link rel="next" href="node12.html" />
<meta name='aesop' content='information' />
<title>2.6 Controllers</title>
</head>
<body>
<DIV CLASS="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="2.5 UI Composition"
  href="node10.html"><img src='previous.png'
  border='0' height='32'  alt='Previous Page' width='32' /></A></td>
<td class='online-navigation'><a rel="parent" title="2 The Kiwi FrameWork"
  href="person.html"><img src='up.png'
  border='0' height='32'  alt='Up One Level' width='32' /></A></td>
<td class='online-navigation'><a rel="next" title="2.6.1 Default Widget Focus"
  href="node12.html"><img src='next.png'
  border='0' height='32'  alt='Next Page' width='32' /></A></td>
<td align="center" width="100%">Developing applications with Kiwi</td>
<td class='online-navigation'><img src='blank.png'
  border='0' height='32'  alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
  border='0' height='32'  alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
  border='0' height='32'  alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="node10.html">2.5 UI Composition</A>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="person.html">2 The Kiwi FrameWork</A>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="node12.html">2.6.1 Default Widget Focus</A>
</div>
<hr /></div>
</DIV>
<!--End of Navigation Panel-->

<H2><A NAME="SECTION000260000000000000000"></A>
<A NAME="callbacks"></A>
<BR>
2.6 Controllers
</H2>

<P>
In GTK+, all user events are interpreted by signals that are generated
by the widgets that are manipulated. This means obvious stuff like
button clicks and typing text into a <tt class="class">gtk.Entry</tt>, but it also
includes less obvious events like the initial rendering of the widget
and moving the mouse over a widget. To a signal, we can attach a
function that is called when it is triggered, and this function is
usually called a <B>signal handler</B>.

<P>
Many widgets have default handlers attached to their signals (these are
coded in the actual GTK+ source code); a default handler, for example,
is what makes the text that you type into an Entry actually display
inside its white box, and what makes the checkbutton depress and change
state when you click on it. However, there are many cases when you want
to do something special based on a certain signal occurring. A pushbutton
(<tt class="class">gtk.Button</tt>) is a good example: it doesn't do anything by default
when clicked beyond depressing, so you practically always will want to
connect to its "clicked" signal. Developing a graphical application
involves selecting which signals you think are important in the
interface widgets, and attaching functions to them.

<P>
In Kiwi, we suggest grouping the relevant signal handlers for an
interface into a class. This means that instead of using a number of
independent functions, the signal handlers are really methods of
a class. This class is called the <tt class="class">Controller</tt>. The
<tt class="class">Controller</tt> is conceptually the part of the framework that
handles events that are generated in the UI; click a button, a
controller method is called.

<P>
Since the View holds the interface, it makes sense to attach a
controller to each view<A NAME="tex2html4"
  HREF="#foot181"><SUP>4</SUP></A>, and vice-versa; the Controller constructor takes a
View instance and ties itself to it. Since the controller needs to
define special methods, it should be subclassed in your code, and the
methods implemented.

<P>
The Kiwi Controller has a special feature: if you write your method
names using a certain syntax, it "discovers" what widget and signal you
want, and attaches the handler automatically for you. This works for any
type of View, even BaseViews, which means no more messing around with
<code>signal_autoconnect()</code> and that pesky signal dialog in Glade. The
handler's method name should be written as follows:

<P>

<OL>
<LI>Start the name with <code>on_</code> or <code>after_</code>. Use <code>on_</code> to
connect before the default handler for that widget's signal; use
<code>after_</code> to connect after it. It is more common to use
<code>on_</code><A NAME="tex2html5"
  HREF="#foot534"><SUP>5</SUP></A>.

<P>
</LI>
<LI>Add the widget name: this is the name of the View's instance
variable for that widget.  If your view has a widget called
<code>quitbutton</code>, you would use "quitbutton".

<P>
</LI>
<LI>Follow the widget name by two underscores (<code>__</code>).

<P>
</LI>
<LI>Finish the name by appending the signal name you want to capture.
For instance, if you wanted to handle that quitbutton's <code>clicked</code>
signal, you would use "clicked". The final method name would be
<code>on_quitbutton__clicked</code>.
</LI>
</OL>

<P>
Note that the widget must be attached <I>directly</I> to the controller's
corresponding View; it can't be attached using this syntax to a slave of
that view, for instance (you'll have to call <code>connect()</code> directly
in that case).

<P>
Let's see a simple example to make
these concepts more concrete (included in the Kiwi tarball at
<span class="file">Kiwi/examples/framework/faren/faren.py</span>):

<P>
<DIV ALIGN="CENTER">
<IMG
  ALIGN="BOTTOM" BORDER="0"
 SRC="img6.png"
 ALT="\includegraphics[scale=0.905]{images/faren.eps}">

</DIV>

<P>
<BR>
<PRE  CLASS="verbatim">#!/usr/bin/env python
import gtk

from kiwi.controllers import BaseController
from kiwi.ui.views import BaseView
from kiwi.ui.gadgets import quit_if_last

class FarenControl(BaseController):

    def on_quitbutton__clicked(self, *args):
        self.view.hide_and_quit()

    def after_temperature__insert_text(self, entry, *args):
        try:
            temp = float(entry.get_text())
        except ValueError:
            temp = 0
        celsius = (temp - 32) * 5/9.0
        farenheit = (temp * 9/5.0) + 32
        self.view.celsius.set_text("%.2f" % celsius)
        self.view.farenheit.set_text("%.2f" % farenheit)

widgets = ["quitbutton", "temperature", "celsius", "farenheit"]
view = BaseView(gladefile="faren", delete_handler=quit_if_last,
                widgets=widgets)
ctl = FarenControl(view)
view.show()
gtk.main()
</PRE>
<P>
Let's have a look at the code. I define a Controller
<tt class="class">FarenControl</tt> that inherits from <tt class="class">BaseController</tt>, and
which defines two methods that are signal handlers - one for the
"clicked" event for the widget <code>quitbutton</code>, and another for the
"insert_text" signal for <code>temperature</code>. I attach the view to the
controller, and tell the view to show itself and run the event loop. Not
much else is worth noting, apart from the fact that the signal handlers
receive the widget as the first parameter, and that the GTK+ text
widgets (gtk.Entry, gtk.Label, gtk.Text) usually take and return strings,
which makes us do conversion here and there.

<P>
Thus, the event loop now has two signal handlers that will be triggered
according to the user's interaction: one called when clicking the
quitbutton and one when inserting text into the entry. The user can type
numbers into the entry, and through
<code>after_temperature__insert_text()</code>, the celsius and farenheit
labels are changed automatically. Clicking quit calls a special method
in the view, <code>hide_and_quit()</code>, that hides the window and quits
the event loop. Note that the widgets "celsius" and "farenheit" are
empty labels that appear right next to the labels that <I>are written</I>
"Celsius" and "Farenheit"; if you are confused look at the glade file
<em class="citetitle"><a
 href="faren.glade"
 title="faren.glade"
 >faren.glade</a></em>.

<P>
<BR><HR><H4>Footnotes</H4>
<DL>
<DT><A NAME="foot181">... view</A><A
 href="callbacks.html#tex2html4"><SUP>4</SUP></A></DT>
<DD>Ancient versions of Kiwi had a
MultiView class, that held various subviews for portions of it, and
required one controller for each subview. The new SlaveView approach is
nicer, because it allows reusing the actual interface in a much more
flexible manner.

</DD>
<DT><A NAME="foot534">...on_</A><A
 href="callbacks.html#tex2html5"><SUP>5</SUP></A></DT>
<DD>Hint: if you are connecting
to a <tt class="class">gtk.Entry</tt>'s <code>insert_text</code> signal and you want to use
<code>entry.get_text()</code>, use <code>after_entrywidget__insert_text</code>
-- the default signal handler is responsible for inserting the text
into the entry and you will need it to run before your handler.

</DD>
</DL>
<p><br /></p><hr class='online-navigation' />
<div class='online-navigation'>
<!--Table of Child-Links-->
<A NAME="CHILD_LINKS"><STRONG>Subsections</STRONG></a>

<UL CLASS="ChildLinks">
<LI><A href="node12.html">2.6.1 Default Widget Focus</a>
<LI><A href="node13.html">2.6.2 Advanced Controllers</a>
</ul>
<!--End of Table of Child-Links-->
</div>

<DIV CLASS="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="2.5 UI Composition"
  href="node10.html"><img src='previous.png'
  border='0' height='32'  alt='Previous Page' width='32' /></A></td>
<td class='online-navigation'><a rel="parent" title="2 The Kiwi FrameWork"
  href="person.html"><img src='up.png'
  border='0' height='32'  alt='Up One Level' width='32' /></A></td>
<td class='online-navigation'><a rel="next" title="2.6.1 Default Widget Focus"
  href="node12.html"><img src='next.png'
  border='0' height='32'  alt='Next Page' width='32' /></A></td>
<td align="center" width="100%">Developing applications with Kiwi</td>
<td class='online-navigation'><img src='blank.png'
  border='0' height='32'  alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
  border='0' height='32'  alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
  border='0' height='32'  alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="node10.html">2.5 UI Composition</A>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="person.html">2 The Kiwi FrameWork</A>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="node12.html">2.6.1 Default Widget Focus</A>
</div>
</div>
<hr />
<span class="release-info">Release 1.9.22, documentation updated on August, 2006.</span>
</DIV>
<!--End of Navigation Panel-->

</BODY>
</HTML>