主に 2 FLTK機能と関数Sleep(miliseconds)
を使用して、針(秒、分、時)が動く「アナログ時計」のグラフィック表現を実装しています:
main.cpp
:
#include "iostream"
#include "GUI.h"
#include "Window.h"
using namespace Graph_lib;
#include "AnalogClock.h"
int main ()
try {
Analog_clock ac (Point (700,30), "Analog clock");
return gui_main ();
} catch (exception &e) {
cerr << e.what () << endl;
getchar();
}
AnalogClock.h
:
#pragma once
#define PI 3.14159265
/*
class Analog_clock
It creates a GUI representing an analog clock
with three indicators: hour, minute, second
and a fancy dial.
*/
class Analog_clock: public Window {
public:
Analog_clock (Point xy, const string &label);
private:
// background image
Image clock_dial;
// data representing second, minute and hour
Line* second_indicator;
Line* minute_indicator;
Line* hour_indicator;
// helper functions
Point rotate (Point initial, Point pivot, double angle);
void set_clock ();
void run_clock ();
// action functions
void increment_second ();
void increment_minute ();
void increment_hour ();
// callback functions
/*
typedef void* Address;
template<class W> W& reference_to (Address pw) {
return *static_cast<W*>(pw);
}
*/
static void cb_seconds (Address, Address pw) { reference_to<Analog_clock>(pw).increment_second (); }
static void cb_minutes (Address, Address pw) { reference_to<Analog_clock>(pw).increment_minute (); }
static void cb_hours (Address, Address pw) { reference_to<Analog_clock>(pw).increment_hour (); }
};
//------------------------------------------------------------------------------------------------------------------------
// class member implementations
/*
class constructor: Analog_clock()
It initializes a window containing
an image (dial) and three lines
(indicators), together with a
function that runs the clock utilizing
the machine clock.
*/
Analog_clock::Analog_clock (Point xy, const string &label)
: Window (xy, 480, 460 , label),
clock_dial (Point (0, 0), "Chapter16Exercise6.gif"),
second_indicator (nullptr),
minute_indicator (nullptr),
hour_indicator (nullptr)
{
attach (clock_dial);
set_clock ();
run_clock ();
}
// helper function
/*
Member function: rotate ();
Use: -
It is used to rotate the clock indicators
around the center point at an angle
corresponding to second, minute and hour.
*/
Point Analog_clock::rotate (Point initial, Point pivot, double angle) {
return Point((cos(angle) * (initial.x - pivot.x)) - (sin(angle) * (initial.y - pivot.y)) + pivot.x,
(sin(angle) * (initial.x - pivot.x)) + (cos(angle) * (initial.y - pivot.y)) + pivot.y);
}
/*
Member function: set_clock ()
Use: -
It initializes the data members
representing clock indicators to
initial value: pointing at 12 o'clock.
*/
void Analog_clock::set_clock () {
Point clock_center (x_max () / 2. - 2, y_max () / 2.);
// set seconds
const int second_indicator_length = 150;
Point twelve_o_clock_s (x_max () / 2. - 2, y_max () / 2. - second_indicator_length);
second_indicator = new Line (clock_center, twelve_o_clock_s);
second_indicator->set_style (Line_style (Line_style::solid, 2));
second_indicator->set_color (Color::red);
// set minutes
const int minute_indicator_length = 150;
Point twelve_o_clock_m (x_max () / 2. - 2, y_max() / 2. - minute_indicator_length);
minute_indicator = new Line (clock_center, twelve_o_clock_m);
minute_indicator->set_style (Line_style (Line_style::solid, 8));
// set hours
const int hour_indicator_length = 50;
Point twelve_o_clock (x_max () / 2. - 2, y_max () / 2. - hour_indicator_length);
hour_indicator = new Line (clock_center, twelve_o_clock);
hour_indicator->set_style (Line_style (Line_style::solid, 8));
// attach in the right order
attach (*minute_indicator);
attach (*hour_indicator);
attach (*second_indicator);
}
/*
Member function: run_clock ()
Use: -
It updates the clock time by
invoking the functions responsible
for the rotation of the indicators
at a specific interval defined with
the help of the functions: clock ()
and sleep ().
*/
void Analog_clock::run_clock () {
// get real time and set the clock
// ...
// run the clock
while (true) {
for (auto i = 0; i < 60; i++) {
for (auto i = 0; i < 60; i++) {
cb_seconds (0, this);
Sleep (1000);
}
cb_minutes (0, this);
}
cb_hours (0, this);
}
}
// action functions
/*
Member function: increment_second ()
Use: -
It increments the second indicator by
rotating the line that represents it
by an angle of 6 degrees.
*/
void Analog_clock::increment_second () {
Point center = second_indicator->point (0);
Point old_time = second_indicator->point (1);
// rotate 6 degrees (6 degrees x 60 seconds = 360 one rotation)
double angle_radians = ((6.) * PI) / 180.;
Point new_time = rotate (old_time, center, angle_radians);
// delete old indicator, create new one and attach it
detach (*second_indicator);
second_indicator = new Line (center, new_time);
second_indicator->set_style (Line_style (Line_style::solid, 2));
second_indicator->set_color (Color::red);
attach (*second_indicator);
// redraw ();
draw();
}
/*
Member function: increment_minute ()
Use: -
It increments the minute indicator by
rotating the line that represents it
by an angle of 6 degrees.
*/
void Analog_clock::increment_minute () {
Point center = minute_indicator->point (0);
Point old_time = minute_indicator->point (1);
// rotate 6 degrees (6 degrees x 60 seconds = 360 one rotation)
double angle_radians = ((6.) * PI) / 180.;
Point new_time = rotate (old_time, center, angle_radians);
// delete old indicator, create new one and attach it
detach (*minute_indicator);
minute_indicator = new Line (center, new_time);
minute_indicator->set_style (Line_style (Line_style::solid, 8));
attach (*minute_indicator);
// redraw ();
draw();
}
/*
Member function: increment_hour ()
Use: -
It increments the hour indicator by
rotating the line that represents it
by an angle of 30 degrees.
*/
void Analog_clock::increment_hour () {
Point center = hour_indicator->point (0);
Point old_time = hour_indicator->point (1);
// rotate 6 degrees (6 degrees x 60 seconds = 360 one rotation)
double angle_radians = ((30.) * PI) / 180.;
Point new_time = rotate (old_time, center, angle_radians);
// delete old indicator, create new one and attach it
detach (*hour_indicator);
hour_indicator = new Line (center, new_time);
hour_indicator->set_style (Line_style (Line_style::solid, 8));
attach (*hour_indicator);
// redraw ();
draw ();
}
結果:
33秒後:
1分24秒後:
質問:
-
上記のコードは問題ないように見えますが、排除できる間違いはありますか?
-
時計をよりスムーズに更新する方法。毎秒「点滅」していませんか?
-
increment_second () / minute () / hour ()
内のコメント付き関数redraw ()
を使用すると、指定したウィンドウ内で、run_clock ()
内のループが終了した後に一度だけクロックが表示されます。一方、現在の実装では、つまり関数draw ()
を使用すると、クロックは指定されたウィンドウ内にないことで毎秒更新され、開いている残りのウィンドウと干渉します。
1。演習6 B. Stroustrupの第16章:「C ++プログラミング言語:原則と実践」