File: ch17.html

package info (click to toggle)
gtkmm2.0 2.2.12-2
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 56,872 kB
  • ctags: 51,600
  • sloc: xml: 73,173; cpp: 20,565; sh: 8,608; perl: 2,702; makefile: 1,233
file content (204 lines) | stat: -rw-r--r-- 8,421 bytes parent folder | download | duplicates (2)
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
<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Chapter17.Timeouts, I/O and Idle Functions </title><meta name="generator" content="DocBook XSL Stylesheets V1.64.1"><link rel="home" href="index.html" title="Programming with gtkmm2"><link rel="up" href="index.html" title="Programming with gtkmm2"><link rel="previous" href="ch16s04.html" title="Examples"><link rel="next" href="ch17s02.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">Chapter17.Timeouts, I/O and Idle Functions </th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch16s04.html">Prev</a></td><th width="60%" align="center"></th><td width="20%" align="right"><a accesskey="n" href="ch17s02.html">Next</a></td></tr></table><hr></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="sec-timeouts"></a>Chapter17.Timeouts, I/O and Idle Functions </h2></div></div><div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="ch17.html#id2518043">Timeouts</a></span></dt><dt><span class="sect1"><a href="ch17s02.html">Monitoring I/O</a></span></dt><dt><span class="sect1"><a href="ch17s03.html">Idle Functions</a></span></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2518043"></a>Timeouts</h2></div></div><div></div></div><p>
 You may be wondering how to make gtkmm do useful work while it's
idling along (well, sleeping actually) in <tt class="literal">Gtk::Main::run()</tt>.  Happily,
you have several options. Using the following methods you can create
a timeout method that will be called every few milliseconds.
</p><p>
</p><pre class="programlisting">
SigC::Connection Glib::SignalTimeout::connect(const SigC::Slot0&lt;bool&gt;&amp; slot, unsigned int interval, int priority = Glib::PRIORITY_DEFAULT);
</pre><p>
</p><p>
The first argument is a slot 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 <tt class="literal">SigC::Connection</tt> object that can be
used to deactivate the connection.
</p><p>

</p><pre class="programlisting">
MyConnection.disconnect();
</pre><p>
</p><p>
to destroy the connection. Another way of destroying the Connection
is your signal handler. It has to be of the type
<tt class="literal">SigC::Slot0&lt;bool&gt;</tt>. As you see from the definition your
signal handler has to return a value of the type <tt class="literal">bool</tt>.  A
definition of a sample method might look like this:
</p><p>



</p><pre class="programlisting">
bool MyCallback() { std::cout &lt;&lt; "Hello World!\n"; return true; }
</pre><p>



</p><p>
You can stop the timeout method by returning <tt class="literal">false</tt> from
your signal handler.  Therefore, if you want your
method to be called repeatedly, it should return <tt class="literal">true</tt>.
</p><p>
Here's an example of this technique:
</p><p><a href="../../../examples/book/timeout/" target="_top">Source Code</a></p><p>File: timerexample.h
</p><pre class="programlisting">
#ifndef GTKMM_EXAMPLE_TIMEREXAMPLE_H
#define GTKMM_EXAMPLE_TIMEREXAMPLE_H

#include &lt;gtkmm.h&gt;
#include &lt;iostream&gt;
#include &lt;map&gt;

class TimerExample : public Gtk::Window
{
public:
  TimerExample();

protected:
  // signal handlers
  void on_button_add_timer();
  void on_button_delete_timer();

  // This is the callback function the timeout will call
  bool on_timeout(int timer_number);

  // Member data:

  Gtk::HBox 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&lt;int, SigC::Connection&gt; 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&lt;int, int&gt; m_counters;
};

#endif // GTKMM_EXAMPLE_TIMEREXAMPLE_H
</pre><p>
</p><p>File: main.cc
</p><pre class="programlisting">
#include "timerexample.h"
#include &lt;gtkmm/main.h&gt;

int main (int argc, char *argv[])
{
  Gtk::Main app(argc, argv);

  TimerExample example;
  Gtk::Main::run(example);

  return 0;
}
</pre><p>
</p><p>File: timerexample.cc
</p><pre class="programlisting">
#include "timerexample.h"

TimerExample::TimerExample() :
  m_Box(true, 10),
  m_ButtonAddTimer(Gtk::Stock::ADD), // use Gtk::Stock wherever possible for buttons, etc.
  m_ButtonDeleteTimer(Gtk::Stock::REMOVE),
  m_ButtonQuit(Gtk::Stock::QUIT),
  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
{
  set_border_width(10);

  add(m_Box);
  m_Box.pack_start(m_ButtonAddTimer);
  m_Box.pack_start(m_ButtonDeleteTimer);
  m_Box.pack_start(m_ButtonQuit);

  // Connect the three buttons:
  m_ButtonQuit.signal_clicked().connect(SigC::slot(*this, &amp;Gtk::Widget::hide));
  m_ButtonAddTimer.signal_clicked().connect(SigC::slot(*this,&amp;TimerExample::on_button_add_timer));
  m_ButtonDeleteTimer.signal_clicked().connect(SigC::slot(*this,&amp;TimerExample::on_button_delete_timer));

  show_all_children(); 
}

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::Slot0&lt;bool&gt; my_slot = SigC::bind(SigC::slot(*this, &amp;TimerExample::on_timeout), m_timer_number);

  // This is where we connect the slot to the Glib::signal_timeout()
  SigC::Connection 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 &lt;&lt; "added timeout " &lt;&lt; m_timer_number++ &lt;&lt; std::endl;
}

void TimerExample::on_button_delete_timer()
{
  // any timers?
  if(m_timers.empty())
  {
    // no timers left
    std::cout &lt;&lt; "Sorry, there are no timers left." &lt;&lt; std::endl;
  }
  else
  {
    // get the number of the first timer
    int timer_number = m_timers.begin()-&gt;first;
 
    // Give some info to the user:
    std::cout &lt;&lt; "manually disconnecting timer " &lt;&lt; timer_number &lt;&lt; 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 &lt;&lt; "This is timer " &lt;&lt; timer_number;

  // decrement and check counter value
  if (--m_counters[timer_number] == 0)
  {
    std::cout &lt;&lt; " being disconnected" &lt;&lt;  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 &lt;&lt; " - " &lt;&lt; m_counters[timer_number] &lt;&lt; "/" &lt;&lt; count_value &lt;&lt; std::endl;
 
 // Keep going (do not disconnect yet):
  return true;
}
</pre><p>
</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch16s04.html">Prev</a></td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"><a accesskey="n" href="ch17s02.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Examples</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">Monitoring I/O</td></tr></table></div></body></html>