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
|
package AnalogClock;
use Qt;
use Qt::isa qw(Qt::Widget);
use Qt::slots
setTime => ['const QTime&'],
drawClock => ['QPainter*'],
timeout => [];
use Qt::attributes qw(
clickPos
_time
);
#
# Constructs an analog clock widget that uses an internal QTimer
#
sub NEW {
shift->SUPER::NEW(@_);
_time = Qt::Time::currentTime(); # get current time
my $internalTimer = Qt::Timer(this); # create internal timer
this->connect($internalTimer, SIGNAL('timeout()'), SLOT('timeout()'));
$internalTimer->start(5000); # emit signal every 5 seconds
}
sub mousePressEvent {
my $e = shift;
if(isTopLevel()) {
# Lack of operators is really noticable here
my $topLeft = Qt::Point(
geometry()->topLeft->x - frameGeometry()->topLeft->x,
geometry()->topLeft->y - frameGeometry()->topLeft->y
);
clickPos = Qt::Point($e->pos->x + $topLeft->x,
$e->pos->y + $topLeft->y);
}
}
sub mouseMoveEvent {
my $e = shift;
if(isTopLevel()) {
move(Qt::Point($e->globalPos->x - clickPos->x,
$e->globalPos->y - clickPos->y));
}
}
sub setTime {
my $t = shift;
timeout();
}
#
# The QTimer::timeout() signal is received by this slot.
#
sub timeout {
my $new_time = Qt::Time::currentTime(); # get the current time
_time = _time->addSecs(5);
if($new_time->minute != _time->minute) { # minute has changed
if(autoMask()) {
updateMask();
} else {
update();
}
}
}
sub paintEvent {
return if autoMask();
my $paint = Qt::Painter(this);
$paint->setBrush(colorGroup()->foreground);
drawClock($paint);
}
# If clock is transparent, we use updateMask()
# instead of paintEvent()
sub updateMask { # paint clock mask
my $bm = Qt::Bitmap(size());
$bm->fill(&color0); # transparent
my $paint = Qt::Painter;
$paint->begin($bm, this);
$paint->setBrush(&color1); # use non-transparent color
$paint->setPen(&color1);
drawClock($paint);
$paint->end;
setMask($bm);
}
#
# The clock is painted using a 1000x1000 square coordinate system, in
# the centered square, as big as possible. The painter's pen and
# brush colors are used.
#
sub drawClock {
my $paint = shift;
$paint->save;
$paint->setWindow(-500,-500, 1000,1000);
my $v = $paint->viewport;
my $d = min($v->width, $v->height);
$paint->setViewport($v->left + ($v->width-$d)/2,
$v->top - ($v->height-$d)/2, $d, $d);
# _time = Qt::Time::currentTime();
my $pts = Qt::PointArray();
$paint->save;
$paint->rotate(30*(_time->hour%12-3) + _time->minute/2);
$pts->setPoints([-20,0, 0,-20, 300,0, 0,20]);
$paint->drawConvexPolygon($pts);
$paint->restore;
$paint->save;
$paint->rotate((_time->minute-15)*6);
$pts->setPoints([-10,0, 0,-10, 400,0, 0,10]);
$paint->drawConvexPolygon($pts);
$paint->restore;
for(1 .. 12) {
$paint->drawLine(440,0, 460,0);
$paint->rotate(30);
}
$paint->restore;
}
sub setAutoMask {
my $b = shift;
setBackgroundMode($b ? &PaletteForeground : &PaletteBackground);
Qt::Widget::setAutoMask($b);
}
1;
|