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
|
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="highlight.min.css">
<script src="highlight.min.js"></script><script>
hljs.configure({languages: ['cpp']});
hljs.highlightAll();
</script><title>Appendix B. Signals</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
<link rel="home" href="index.html" title="Programming with gtkmm 4">
<link rel="up" href="index.html" title="Programming with gtkmm 4">
<link rel="prev" href="sec-refptr-constness.html" title="Constness">
<link rel="next" href="sec-writing-signal-handlers.html" title="Writing signal handlers">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr><th colspan="3" align="center">Appendix B. Signals</th></tr>
<tr>
<td width="20%" align="left">
<a accesskey="p" href="sec-refptr-constness.html"><img src="icons/prev.png" alt="Prev"></a> </td>
<th width="60%" align="center"> </th>
<td width="20%" align="right"> <a accesskey="n" href="sec-writing-signal-handlers.html"><img src="icons/next.png" alt="Next"></a>
</td>
</tr>
</table>
<hr>
</div>
<div class="appendix">
<div class="titlepage"><div><div><h1 class="title">
<a name="chapter-signals"></a>Appendix B. Signals</h1></div></div></div>
<div class="toc">
<p><b>Table of Contents</b></p>
<ul class="toc">
<li><span class="section"><a href="chapter-signals.html#sec-connecting-signal-handlers">Connecting signal handlers</a></span></li>
<li><span class="section"><a href="sec-writing-signal-handlers.html">Writing signal handlers</a></span></li>
<li><span class="section"><a href="sec-disconnecting-signal-handlers.html">Disconnecting signal handlers</a></span></li>
<li><span class="section"><a href="sec-overriding-default-signal-handlers.html">Overriding default signal handlers</a></span></li>
<li><span class="section"><a href="sec-binding-extra-arguments.html">Binding extra arguments</a></span></li>
<li><span class="section"><a href="sec-eventsignals.html">Event signals</a></span></li>
<li><span class="section"><a href="sec-exceptions-in-signal-handlers.html">Exceptions in signal handlers</a></span></li>
</ul>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="sec-connecting-signal-handlers"></a>Connecting signal handlers</h2></div></div></div>
<p>
<span class="application">gtkmm</span> widget classes have signal accessor methods, such as
<code class="methodname">Gtk::Button::signal_clicked()</code>, which allow you to connect
your signal handler. Thanks to the flexibility of
<span class="application">libsigc++</span>, the callback library used by <span class="application">gtkmm</span>, the
signal handler can be almost any kind of function, but you will probably want
to use a class method. Among <span class="application">GTK</span> C coders, these
signal handlers are often named callbacks.
</p>
<p>
Here's an example of a signal handler being connected to a signal:
</p>
<pre class="programlisting"><code class="code">
#include <gtkmm/button.h>
void on_button_clicked()
{
std::cout << "Hello World" << std::endl;
}
class some_class
{
public:
some_class
{
button.signal_clicked().connect(sigc::ptr_fun(&on_button_clicked));
}
private:
Gtk::Button button {"Hello World"};
};
</code></pre>
<p>
There's rather a lot to think about in this (non-functional) code.
First let's identify the parties involved:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<p>
The signal handler is <code class="methodname">on_button_clicked()</code>.
</p>
</li>
<li class="listitem">
<p>
We're hooking it up to the <code class="classname">Gtk::Button</code> object called
<code class="varname">button</code>.
</p>
</li>
<li class="listitem">
<p>
When the Button emits its <code class="literal">clicked</code> signal,
<code class="methodname">on_button_clicked()</code> will be called.
</p>
</li>
</ul></div>
<p>
Now let's look at the connection again:
</p>
<pre class="programlisting"><code class="code"> ...
button.signal_clicked().connect(sigc::ptr_fun(&on_button_clicked));
...
</code></pre>
<p>
Note that we don't pass a pointer to <code class="methodname">on_button_clicked()</code>
directly to the signal's <code class="methodname">connect()</code> method. Instead, we
call <code class="function">sigc::ptr_fun()</code>, and pass the result to
<code class="methodname">connect()</code>.
</p>
<p>
<code class="function">sigc::ptr_fun()</code> generates a <code class="classname">sigc::slot</code>.
A slot is an object which
looks and feels like a function, but is actually an object. These are also
known as function objects, or functors.
<code class="function">sigc::ptr_fun()</code> generates a slot for a standalone function or static method.
<code class="function">sigc::mem_fun()</code> generates a slot for a member method of a particular instance.
</p>
<p>
A C++ lambda expression is a functor which can be implicitly converted to a
<code class="classname">sigc::slot</code> in the call to <code class="methodname">connect()</code>.
A lambda expression can be used instead of <code class="function">sigc::ptr_fun()</code>.
It's also possible to use a lambda expression instead of <code class="function">sigc::mem_fun()</code>,
but then you won't get automatic disconnection of the signal handler when a
<code class="classname">sigc::trackable</code>-derived object goes out of scope.
</p>
<p>
Here's a slightly larger example of slots in action:
</p>
<pre class="programlisting"><code class="code">
#include <gtkmm/button.h>
void on_button_clicked()
{
std::cout << "Hello World" << std::endl;
}
class some_class
{
public:
some_class
{
button.signal_clicked().connect(sigc::ptr_fun(&on_button_clicked));
button.signal_clicked().connect(sigc::mem_fun(*this, &some_class::on_button_clicked));
}
void on_button_clicked();
private:
Gtk::Button button {"Hello World"};
};
</code></pre>
<p>
The first call to <code class="methodname">connect()</code> is just like the one we saw
last time; nothing new here.</p>
<p>The next is more interesting.
<code class="function">sigc::mem_fun()</code> is called with two arguments. The first
argument is <em class="parameter"><code>*this</code></em>, which is the object that our
new slot will be pointing at. The second argument is a pointer to one of its
methods. This particular version of <code class="function">sigc::mem_fun()</code>
creates a slot which will, when "called", call the pointed-to method of the
specified object.
</p>
<p>
Another thing to note about this example is that we made the call to
<code class="methodname">connect()</code> twice for the same signal object. This is
perfectly fine - when the button is clicked, both signal handlers will be
called.
</p>
<p>
We just told you that the button's <code class="literal">clicked</code> signal is expecting
to call a method with no arguments. All signals have
requirements like this - you can't hook a function with two arguments
to a signal expecting none (unless you use an adapter, such as
<code class="function">sigc::bind()</code>, of course). Therefore, it's important to
know what type of signal handler you'll be expected to connect to a given
signal.
</p>
</div>
</div>
<div class="navfooter">
<hr>
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left">
<a accesskey="p" href="sec-refptr-constness.html"><img src="icons/prev.png" alt="Prev"></a> </td>
<td width="20%" align="center"> </td>
<td width="40%" align="right"> <a accesskey="n" href="sec-writing-signal-handlers.html"><img src="icons/next.png" alt="Next"></a>
</td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Constness </td>
<td width="20%" align="center"><a accesskey="h" href="index.html"><img src="icons/home.png" alt="Home"></a></td>
<td width="40%" align="right" valign="top"> Writing signal handlers</td>
</tr>
</table>
</div>
</body>
</html>
|