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
|
<!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="node15.html" />
<link rel="prev" href="callbacks.html" />
<link rel="parent" href="person.html" />
<link rel="next" href="node15.html" />
<meta name='aesop' content='information' />
<title>2.7 UI Delegates</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.6.2 Advanced Controllers"
href="node13.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.8 UI Composition with"
href="node15.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="node13.html">2.6.2 Advanced Controllers</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="node15.html">2.8 UI Composition with</A>
</div>
<hr /></div>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000270000000000000000">
2.7 UI Delegates</A>
</H2>
<P>
The UI Delegate classes, located in the <tt class="module">kiwi.ui.delegates</tt> module, use
multiple inheritance, being derived from both a View and a Controller.
This means they combine functionality from both into a single class: not
only does it specify the interface, it also handles the widget signals.
It's the "can't beat them, join them" solution to the V+C coupling
problem, and it's used in Swing, MFC and Bakery, a C++ framework for
GTK+.
<P>
The <tt class="class">Delegate</tt> class is a combination of <tt class="class">BaseView</tt> and
<tt class="class">BaseController</tt>. You can use it to create your interface
programatically and then hook up handlers to it, just like you would do
to individual views and controllers. A very simple (yes, I too get bored
of hand-coding PyGTK widgets) example follows, found in the distribution
as <span class="file">examples/framework/simple.py</span>:
<P>
<DIV ALIGN="CENTER">
<IMG
ALIGN="BOTTOM" BORDER="0"
SRC="img7.png"
ALT="\includegraphics[scale=0.905]{images/simple2.eps}">
</DIV>
<P>
<BR>
<PRE CLASS="verbatim">#!/usr/bin/env python
import gtk
from kiwi.ui.delegates import Delegate
class Hello(Delegate):
def __init__(self):
self.index = 0
self.text = ["I've decided to take my work back underground",
"To keep it from falling into the wrong hands."]
topwidget = gtk.Window()
topwidget.set_title("So...")
self.button = gtk.Button(self.text[self.index])
self.button.show()
topwidget.add(self.button)
Delegate.__init__(self, topwidget, delete_handler=gtk.main_quit)
# focus button, our only widget
self.focus_topmost()
def on_button__clicked(self, button):
self.index = self.index + 1
# Two clicks and we're gone
if self.index > 1:
self.hide_and_quit()
# the *handler's* return value disappears into GTK+
return
# update the label of the button
button.set_label(self.text[self.index])
app = Hello()
app.show_and_loop()
</PRE>
<P>
<DIV ALIGN="CENTER">
<IMG
ALIGN="BOTTOM" BORDER="0"
SRC="img8.png"
ALT="\includegraphics[scale=0.905]{images/simple3.eps}">
</DIV>
<P>
As you can see, the Delegate was the only class we needed to inherit
from and instantiate. This makes the amount of infrastructure code go
down significantly, and most single-window applications (and individual
dialogs in multi-window applications) can be implemented with single
Delegate and GladeDelegate subclasses. As an example for using the
GladeDelegate, below is a third version of our temperature conversion
application, <span class="file">examples/Faren/faren3.py</span>:
<P>
<BR>
<PRE CLASS="verbatim">#!/usr/bin/env python
import gtk
from kiwi.ui.delegates import Delegate
class Farenheit(Delegate):
widgets = ["quitbutton", "temperature", "celsius", "farenheit",
"celsius_label" , "farenheit_label", "temperature_label"]
gladefile = "faren"
def __init__(self):
Delegate.__init__(self, delete_handler=self.quit_if_last)
def convert_temperature(self, temp):
farenheit = (temp * 9/5.0) + 32
celsius = (temp - 32) * 5/9.0
return farenheit, celsius
def clear_temperature(self):
self.farenheit.set_text("")
self.celsius.set_text("")
# Signal handlers
def on_quitbutton__clicked(self, *args):
self.hide_and_quit()
def after_temperature__changed(self, entry, *args):
temp = entry.get_text().strip() or None
if temp is None:
self.clear_temperature()
else:
try:
farenheit, celsius = self.convert_temperature(float(temp))
except ValueError:
farenheit = celsius = float('nan')
self.farenheit.set_text("%.2f" % farenheit)
self.celsius.set_text("%.2f" % celsius)
delegate = Farenheit()
delegate.show()
gtk.main()
</PRE>
<P>
As you can see, using the delegates makes a lot of sense in many cases:
the view and controller split isn't essential, and you can end up
with a lot less code with the same functionality at no reduced
maintainability or readability, which is what we are aiming for. For
larger applications, or apps where a lot of very unusual functionality
is required, it may still make sense to use separate Controllers and
Views, but for normal development, stick to delegates; they simplify
things.
<P>
Note that there is also a <tt class="class">SlaveDelegate</tt>, which works like a
normal SlaveView with an attached Controller.
<P>
<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.6.2 Advanced Controllers"
href="node13.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.8 UI Composition with"
href="node15.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="node13.html">2.6.2 Advanced Controllers</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="node15.html">2.8 UI Composition with</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>
|