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 281 282 283 284 285 286 287 288
|
<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>Chapter 24. Timeouts, I/O and Idle Functions</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-keyboardevents-mouse.html" title="Mouse Events">
<link rel="next" href="sec-monitoring-io.html" title="Monitoring I/O">
</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">Chapter 24. Timeouts, I/O and Idle Functions </th></tr>
<tr>
<td width="20%" align="left">
<a accesskey="p" href="sec-keyboardevents-mouse.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-monitoring-io.html"><img src="icons/next.png" alt="Next"></a>
</td>
</tr>
</table>
<hr>
</div>
<div class="chapter">
<div class="titlepage"><div><div><h1 class="title">
<a name="chapter-chapter-timeouts"></a>Chapter 24. Timeouts, I/O and Idle Functions </h1></div></div></div>
<div class="toc">
<p><b>Table of Contents</b></p>
<ul class="toc">
<li><span class="section"><a href="chapter-chapter-timeouts.html#sec-timeouts">Timeouts</a></span></li>
<li><span class="section"><a href="sec-monitoring-io.html">Monitoring I/O</a></span></li>
<li><span class="section"><a href="sec-idle-functions.html">Idle Functions</a></span></li>
</ul>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="sec-timeouts"></a>Timeouts</h2></div></div></div>
<p>
You may be wondering how to make <span class="application">gtkmm</span> do useful work while it's idling along. Happily,
you have several options. Using the following methods you can create a timeout
method that will be called every few milliseconds.
</p>
<pre class="programlisting"><code class="code">sigc::connection Glib::SignalTimeout::connect(const sigc::slot<bool()>& slot,
unsigned int interval, int priority = Glib::PRIORITY_DEFAULT);
</code></pre>
<p>
The first argument is a <code class="classname">slot</code> you wish to have called
when the timeout occurs. The second argument is the number of milliseconds
between calls to that method. You receive a
<code class="classname">sigc::connection</code> object that can be used to deactivate
the connection using its <code class="methodname">disconnect()</code> method:
</p>
<pre class="programlisting"><code class="code">my_connection.disconnect();
</code></pre>
<p>
Another way of destroying the connection is your signal handler.
It has to be of the type <code class="classname">sigc::slot<bool()></code>.
As you see from the definition your signal handler has to return a value of
the type <code class="literal">bool</code>. A definition of a sample method might
look like this:
</p>
<pre class="programlisting"><code class="code">bool MyCallback() { std::cout << "Hello World!\n" << std::endl; return true; }
</code></pre>
<p>
You can stop the timeout method by returning <code class="literal">false</code> from
your signal handler. Therefore, if you want your
method to be called repeatedly, it should return <code class="literal">true</code>.
</p>
<p>
Here's an example of this technique:
</p>
<p><a class="ulink" href="https://gitlab.gnome.org/GNOME/gtkmm-documentation/tree/master/examples/book/timeout/" target="_top">Source Code</a></p>
<p>File: <code class="filename">timerexample.h</code> (For use with gtkmm 4)</p>
<pre class="programlisting"><code class="code">#ifndef GTKMM_EXAMPLE_TIMEREXAMPLE_H
#define GTKMM_EXAMPLE_TIMEREXAMPLE_H
#include <gtkmm.h>
#include <iostream>
#include <map>
class TimerExample : public Gtk::Window
{
public:
TimerExample();
protected:
// signal handlers
void on_button_add_timer();
void on_button_delete_timer();
void on_button_quit();
// This is the callback function the timeout will call
bool on_timeout(int timer_number);
// Member data:
Gtk::Box m_Box;
Gtk::Button m_ButtonAddTimer, m_ButtonDeleteTimer, m_ButtonQuit;
// Keep track of the timers being added:
int m_timer_number;
// These two constants are initialized in the constructor's member initializer:
const int count_value;
const int timeout_value;
// STL map for storing our connections
std::map<int, sigc::connection> m_timers;
// STL map for storing our timer values.
// Each timer counts back from COUNT_VALUE to 0 and is removed when it reaches 0
std::map<int, int> m_counters;
};
#endif // GTKMM_EXAMPLE_TIMEREXAMPLE_H
</code></pre>
<p>File: <code class="filename">main.cc</code> (For use with gtkmm 4)</p>
<pre class="programlisting"><code class="code">#include "timerexample.h"
#include <gtkmm/application.h>
int main (int argc, char *argv[])
{
auto app = Gtk::Application::create("org.gtkmm.example");
return app->make_window_and_run<TimerExample>(argc, argv);
}
</code></pre>
<p>File: <code class="filename">timerexample.cc</code> (For use with gtkmm 4)</p>
<pre class="programlisting"><code class="code">#include "timerexample.h"
TimerExample::TimerExample() :
m_Box(Gtk::Orientation::HORIZONTAL, 10),
m_ButtonAddTimer("_Add", true),
m_ButtonDeleteTimer("_Remove", true),
m_ButtonQuit("_Quit", true),
m_timer_number(0), // start numbering the timers at 0
count_value(5), // each timer will count down 5 times before disconnecting
timeout_value(1500) // 1500 ms = 1.5 seconds
{
m_Box.set_margin(10);
set_child(m_Box);
m_Box.append(m_ButtonAddTimer);
m_Box.append(m_ButtonDeleteTimer);
m_Box.append(m_ButtonQuit);
m_ButtonAddTimer.set_expand();
m_ButtonDeleteTimer.set_expand();
m_ButtonQuit.set_expand();
// Connect the three buttons:
m_ButtonQuit.signal_clicked().connect(sigc::mem_fun(*this,
&TimerExample::on_button_quit));
m_ButtonAddTimer.signal_clicked().connect(sigc::mem_fun(*this,
&TimerExample::on_button_add_timer));
m_ButtonDeleteTimer.signal_clicked().connect(sigc::mem_fun(*this,
&TimerExample::on_button_delete_timer));
}
void TimerExample::on_button_quit()
{
set_visible(false);
}
void TimerExample::on_button_add_timer()
{
// Creation of a new object prevents long lines and shows us a little
// how slots work. We have 0 parameters and bool as a return value
// after calling sigc::bind.
sigc::slot<bool()> my_slot = sigc::bind(sigc::mem_fun(*this,
&TimerExample::on_timeout), m_timer_number);
// This is where we connect the slot to the Glib::signal_timeout()
auto conn = Glib::signal_timeout().connect(my_slot,
timeout_value);
// Remember the connection:
m_timers[m_timer_number] = conn;
// Initialize timer count:
m_counters[m_timer_number] = count_value + 1;
// Print some info to the console for the user:
std::cout << "added timeout " << m_timer_number++ << std::endl;
}
void TimerExample::on_button_delete_timer()
{
// any timers?
if(m_timers.empty())
{
// no timers left
std::cout << "Sorry, there are no timers left." << std::endl;
}
else
{
// get the number of the first timer
int timer_number = m_timers.begin()->first;
// Give some info to the user:
std::cout << "manually disconnecting timer " << timer_number
<< std::endl;
// Remove the entry in the counter values
m_counters.erase(timer_number);
// Diconnect the signal handler:
m_timers[timer_number].disconnect();
// Forget the connection:
m_timers.erase(timer_number);
}
}
bool TimerExample::on_timeout(int timer_number)
{
// Print the timer:
std::cout << "This is timer " << timer_number;
// decrement and check counter value
if (--m_counters[timer_number] == 0)
{
std::cout << " being disconnected" << std::endl;
// delete the counter entry in the STL MAP
m_counters.erase(timer_number);
// delete the connection entry in the STL MAP
m_timers.erase(timer_number);
// Note that we do not have to explicitly call disconnect() on the
// connection since Gtk::Main does this for us when we return false.
return false;
}
// Print the timer value
std::cout << " - " << m_counters[timer_number] << "/"
<< count_value << std::endl;
// Keep going (do not disconnect yet):
return true;
}
</code></pre>
</div>
</div>
<div class="navfooter">
<hr>
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left">
<a accesskey="p" href="sec-keyboardevents-mouse.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-monitoring-io.html"><img src="icons/next.png" alt="Next"></a>
</td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Mouse Events </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"> Monitoring I/O</td>
</tr>
</table>
</div>
</body>
</html>
|