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
|
<!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="node23.html" />
<link rel="prev" href="node21.html" />
<link rel="parent" href="node16.html" />
<link rel="next" href="node23.html" />
<meta name='aesop' content='information' />
<title>2.9.6 Widget support in Proxies</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.9.5 Using Signal Handlers"
href="node21.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.9 Proxies and Models"
href="node16.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.9.7 Models"
href="node23.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="node21.html">2.9.5 Using Signal Handlers</A>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="node16.html">2.9 Proxies and Models</A>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="node23.html">2.9.7 Models</A>
</div>
<hr /></div>
</DIV>
<!--End of Navigation Panel-->
<H3><A NAME="SECTION000296000000000000000">
2.9.6 Widget support in Proxies</A>
</H3>
<P>
The Proxies provide a quite complex mechanism to handle updates in most
of the widgets normally used in "forms". There is a reason for
supporting these widgets: they are easily mapped to model attributes.
This doesn't mean that you can't use other widgets in your Proxy
interface, but there is no automatic update mechanism for it, and you
will have to use your own handlers for them.
<P>
This is a reasonable property - it would be difficult to map what
exactly the state of a gtk.Curve means to the model, for instance - and
the Proxy can be extended in the future to support other widgets (write
me if you are interested in contributing). What follows is a list of
widget types supported, details on the use of them, and details about
setting custom handlers if you need them.
<P>
<UL>
<LI><B>gtk.Entry</B>: the single-line entry box in gtk. Updates the
model on insertion or deletion of every character, which means you
should make sure your accessors take this into account, if you use
accessors (as opposed to <code>setattr()</code>). For instance, if you type in
"Foobar" into the box, the accessor for that model attribute will be
called 6 times.
<P>
<B>Custom handlers</B>: The best signal for hooking a user handler to a
gtk.Entry is "changed", preferably by using <code>after_<I>entryname</I>__changed()</code>; it will be called immediately after the entry
has text inserted or deleted. You can use the individual "insert_text"
or "delete_text" signals if you want to capture one of those specific
events.
<P>
</LI>
<LI><B>gtk.Label</B>: a read-only widget that displays text. It is
useful for displaying model attributes, but it doesn't generate signals
my itself. Use <code>update()</code> in other widget's custom handlers to
notify the Proxy a calculated label's value has changed.
<P>
<B>Custom handlers</B>: The gtk.Label doesn't generate signals.
<P>
</LI>
<LI><B>gtk.OptionMenu (OM)</B>: the menuitem or listbox widget,
containing a list of items. The GTK+ OM has a very evil API by default,
but using the Proxy makes it much simpler; basically, the OM's choice
reflects directly in the model, without extra effort. The OM items can
be created in Glade or straight PyGTK commands; in this case the model
attribute will be set to the text in the label selected. To select an
item, set the model value to the string of text. The model is updated
each time an item is selected in the OM.
<P>
However, this is a very limited way of using the OM, and the recommended
way to build your menu is to use Kiwi's <code>OptionMenu.prefill()</code>
call, which allows you to specify a data value for each item, along with
an extra callback to be called when the an item in the OM is selected.
This way, the model's attribute can be set to any value per item; for
instance, an integer value, or an instance associated with one
particular menuitem.
<P>
If you use <code>OM.prefill()</code>, each item is associated to a data value,
and this value is sent to the model when the item is selected. To select
an item from the model, just set the attribute to the data value, and
the optionmenu updates itself automatically. Set the model attribute to
the data value, and the interface updates automatically. Check the API
for OM for more details.
<P>
<B>Custom handlers</B>: as stated above, use <code>prefill()</code>'s
<code>callback</code> parameter to specify a handler for the OptionMenu.
There is no signal you can connect to directly in GTK+ 1.2.
<P>
</LI>
<LI><B>gtk.RadioButton</B>: Handling the radiobutton is slightly more
complicated, because there are in reality groups of radiobuttons that
bind to a single attribute. In other words, the multiple radiobutton
widgets are connected to a single attribute, which assumes a different
value depending on which button is toggled.
<P>
To perform this grouping<A NAME="tex2html8"
HREF="#foot538"><SUP>8</SUP></A> the Proxy offers a special method called
<code>group_radiobuttons()</code>. This method accepts <code>name</code> and set of
tuples as a parameter, each tuple being in the format <code>(<I>widget_name</I>, <I>widget_value</I>)</code>. <code>name</code> indicates the model
attribute it is to be bound to, <code>widget_name</code> is a string strings
with the name (like used in the widgets list) of the individual
radiobutton to be grouped. Once grouped, these radiobuttons are treated
by the Proxy as a single widget attached to the model attribute, and the
model attribute or accessor will receive the <code>widget_value</code>
associated with the button selected. Setting the model value follows the
same rule as for OM.
<P>
<B>Custom handlers</B>: use the "clicked" signal, connecting after it
(see gtk.Entry above for an <code>after_*()</code> example), and check the
state of the widget if you need to check if it was selected or
de-selected (use <code>widget['active']</code> to check the state in your
callback).
<P>
</LI>
<LI><B>gtk.CheckButton</B> and <B>gtk.ToggleButton</B>: the two-state
button widgets allow values to be set to True and False.
The value is updated every time the button's state changes.
<P>
<B>Custom handlers</B>: use the "clicked" signal, in the same manner as
for gtk.RadioButton.
<P>
</LI>
<LI><B>gtk.SpinButton</B>, <B>gtk.ComboBox</B> and <B>gtk.TextView</B>:
similarly to the gtk.Entry, these widgets are updated every time a
single character is changed in the editable space (yes, the SpinButton
contains an entry). There is no signal that can easily catch when a
gtk.ComboBox list item was selected, which is why we have to handle
things this was for it. In practice, it should work as expected unless
you rely on your accessor being called a specific number of times for
each change, which you shouldn't.
<P>
<B>Custom handlers</B>: gtk.SpinButton and gtk.Text are good candidates for
the "changed" signal; use the same rules as for gtk.Entry. For gtk.Combo,
things are not so easy, because there is no signal it offers you can
catch<A NAME="tex2html9"
HREF="#foot382"><SUP>9</SUP></A>, and the fact that it holds two
subobjects, a gtk.Entry and a gtk.Button, means that you are forced to use
<code>connect()</code> on either of these to get the effect you desire. In
practice, the following works for me (taking into account the fact that
the handler will be called multiple times):
<P>
<div class="verbatim"><pre>
widget = [":combo", ...]
def __init__(self, *args):
# [... in constructor ...]
entry = combo.entry
entry.connect("changed", on_combo_entry__changed)
def on_combo_entry__changed(self, entry, *args):
# [...]
</pre></div>
<P>
</LI>
</UL>
<P>
The code in <span class="file">tests/test_Proxy.py</span> offers a sample of using all the
supported widgets in the same interface, and is highly recommended for
study; it is however a bit too long to include in this text.
<P>
<BR><HR><H4>Footnotes</H4>
<DL>
<DT><A NAME="foot538">... grouping</A><A
HREF="node22.html#tex2html8"><SUP>8</SUP></A></DT>
<DD>Alas, we can't use radiobutton's
<code>group()</code> method to discover groups automatically because it is yet
to be wrapped in PyGTK.
</DD>
<DT><A NAME="foot382">...
catch</A><A
HREF="node22.html#tex2html9"><SUP>9</SUP></A></DT>
<DD>A lively discussion could ensue about gtk.Combo and the
lack of a signal that indicates an option was selected in its list, but
I deliberately choose to avoid it!
</DD>
</DL>
<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.9.5 Using Signal Handlers"
href="node21.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.9 Proxies and Models"
href="node16.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.9.7 Models"
href="node23.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="node21.html">2.9.5 Using Signal Handlers</A>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="node16.html">2.9 Proxies and Models</A>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="node23.html">2.9.7 Models</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>
|