cc在使用Cairo时以256退出 使用Cairo; 使用Gtk; 使用油嘴滑舌; 公共类ClockWidget:DrawingArea{ 私人时间; 专用整数分钟偏移量; 私人拖拉; 公共信号失效时间_改变(整小时、整分钟); 公共时钟部件(){ 添加\
cc在使用Cairo时以256退出cc在使用Cairo时以256退出 使用Cairo; 使用Gtk; 使用油嘴滑舌; 公共类ClockWidget:DrawingArea{ 私人时间; 专用整数分钟偏移量; 私人拖拉; 公共信号失效时间_改变(整小时、整分钟); 公共时钟部件(){ 添加\,gtk,glib,cairo,vala,Gtk,Glib,Cairo,Vala,cc在使用Cairo时以256退出 使用Cairo; 使用Gtk; 使用油嘴滑舌; 公共类ClockWidget:DrawingArea{ 私人时间; 专用整数分钟偏移量; 私人拖拉; 公共信号失效时间_改变(整小时、整分钟); 公共时钟部件(){ 添加\u事件(Gdk.EventMask.BUTTON\u按\u掩码 |Gdk.EventMask.BUTTON\u RELEASE\u MASK |Gdk.EventMask.POINTER\u MOTION\u MASK); 更新(); Time
使用Cairo;
使用Gtk;
使用油嘴滑舌;
公共类ClockWidget:DrawingArea{
私人时间;
专用整数分钟偏移量;
私人拖拉;
公共信号失效时间_改变(整小时、整分钟);
公共时钟部件(){
添加\u事件(Gdk.EventMask.BUTTON\u按\u掩码
|Gdk.EventMask.BUTTON\u RELEASE\u MASK
|Gdk.EventMask.POINTER\u MOTION\u MASK);
更新();
Timeout.add(1000,更新);
设置大小请求(100100);
}
公共覆盖布尔图(Cairo.Context cr){
int y=获得分配的高度()/2;
int x=get\u allocated\u width()/2;
var radius=double.min(获取分配的宽度()/2,
获取分配的高度()/2)-5;
//倒计时
cr.弧(x,y,半径,0,2*3.14);
cr.set\u source\u rgb(1,1,1);
cr.fill_preserve();
cr.set\u source\u rgb(0,0,0);
cr.stroke();
//时钟滴答作响
对于(int i=0;i<12;i++){
内部插图;
cr.save();
如果(i%3==0){
插图=(整数)(0.2*半径);
}否则{
插图=(整数)(0.1*半径);
cr.set_线宽(0.5*cr.get_线宽());
}
cr.move_至(x+(半径-插图)*Math.cos(i*Math.PI/6),
y+(半径-插图)*Math.sin(i*Math.PI/6);
cr.line_至(x+半径*Math.cos(i*Math.PI/6),
y+半径*Math.sin(i*Math.PI/6));
cr.stroke();
cr.restore();
}
//时钟指针
var hours=this.time.hour;
var minutes=this.time.minute+this.minutes\u偏移量;
var seconds=this.time.second;
/*时针:时针每小时旋转30度(pi/6r)+每分钟旋转1/2度(pi/360r)*/
cr.save();
cr.set_线宽(2.5*cr.get_线宽());
cr.move_to(x,y);
cr.line_至(x+半径/2*Math.sin(Math.PI/6*hours
+Math.PI/360*分钟),
y+半径/2*-Math.cos(Math.PI/6*小时
+Math.PI/360*分钟);
cr.stroke();
cr.restore();
//分针:
//分针每分钟旋转6度(pi/30 r)
cr.move_to(x,y);
cr.line_至(x+半径*0.75*Math.sin(Math.PI/30*min),
y+半径*0.75*-Math.cos(Math.PI/30*分钟);
cr.stroke();
//秒针:
//操作与分针相同
cr.save();
cr.set_source_rgb(1,0,0);//红色
cr.move_to(x,y);
cr.line_至(x+半径*0.7*Math.sin(Math.PI/30*s),
y+半径*0.7*-Math.cos(Math.PI/30*秒);
cr.stroke();
cr.restore();
返回false;
}
公共覆盖布尔按钮按下事件(Gdk.EventButton事件){
var minutes=this.time.minute+this.minutes\u偏移量;
//从
// http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
var px=event.x-get_allocated_width()/2;
var py=get\u allocated\u height()/2-event.y;
var lx=Math.sin(Math.PI/30*分钟);
var ly=Math.cos(Math.PI/30*分钟);
var u=lx*px+ly*py;
//在原点的另一边
if(u<0){
返回false;
}
var d2=Math.pow(px-u*lx,2)+Math.pow(py-u*ly,2);
如果(d2<25){//5个像素远离直线
this.draging=true;
打印(“获得分针”);
}
返回false;
}
公共覆盖布尔按钮\释放\事件(Gdk.EventButton事件){
如果(此。拖动){
this.draging=false;
发出时间改变信号((int)event.x,(int)event.y);
}
返回false;
}
公共覆盖布尔运动通知事件(Gdk.EventMotion事件){
如果(此。拖动){
发出时间改变信号((int)event.x,(int)event.y);
}
返回false;
}
专用无效发射时间更改信号(整数x,整数y){
//解码分针
//使原点周围的坐标正常化
x-=获取分配的宽度()/2;
y-=获取分配的高度()/2;
//φ是从北顺时针方向的轴承,使用与相同的几何图形
//我们最初没有对分针进行定位
var phi=数学atan2(x,-y);
if(φ<0){
φ+=数学π*2;
}
var hour=this.time.hour;
变量分钟=(整数)(φ*30/数学π);
//更新偏移量
this.minute\u offset=分钟-this.time.minute;
重新绘制画布();
更改的时间(小时、分钟);
}
私有布尔更新(){
//更新时间
this.time=time.local(time_t());
重新绘制画布();
返回true;//继续运行此事件
}
私有void重绘画布(){
var window=get_window();
如果(空==窗口){
返回;
}
var region=window.get_clip_region();
//通过暴露开罗画布,完全重新绘制它
window.invalidate_region(region,true);
window.process\u更新(true);
}
静态int main(字符串[]args){
Gtk.init(参考参数);
var窗口=新窗口();
var clock=new ClockWidget();
window.add(时钟);
window.destroy.connect(Gtk.main_退出);
赢
using Cairo ;
using Gtk ;
using GLib ;
public class ClockWidget : DrawingArea {
private Time time ;
private int minute_offset ;
private bool dragging ;
public signal void time_changed (int hour, int minute) ;
public ClockWidget () {
add_events (Gdk.EventMask.BUTTON_PRESS_MASK
| Gdk.EventMask.BUTTON_RELEASE_MASK
| Gdk.EventMask.POINTER_MOTION_MASK);
update () ;
Timeout.add (1000, update) ;
set_size_request (100, 100) ;
}
public override bool draw (Cairo.Context cr) {
int y = get_allocated_height () / 2 ;
int x = get_allocated_width () / 2 ;
var radius = double.min (get_allocated_width () / 2,
get_allocated_height () / 2) - 5 ;
// clock back
cr.arc (x, y, radius, 0, 2 * 3.14) ;
cr.set_source_rgb (1, 1, 1) ;
cr.fill_preserve () ;
cr.set_source_rgb (0, 0, 0) ;
cr.stroke () ;
// clock ticks
for (int i = 0; i < 12; i++) {
int inset ;
cr.save () ;
if (i % 3 == 0) {
inset = (int) (0.2 * radius) ;
} else {
inset = (int) (0.1 * radius) ;
cr.set_line_width (0.5 * cr.get_line_width ()) ;
}
cr.move_to (x + (radius - inset) * Math.cos (i * Math.PI / 6),
y + (radius - inset) * Math.sin (i * Math.PI / 6));
cr.line_to (x + radius * Math.cos (i * Math.PI / 6),
y + radius * Math.sin (i * Math.PI / 6));
cr.stroke ();
cr.restore ();
}
// clock hands
var hours = this.time.hour ;
var minutes = this.time.minute + this.minute_offset ;
var seconds = this.time.second ;
/* hour hand: the hour hand is rotated 30 degrees (pi/6r) per hour + 1/2 a degree (pi/360r) per minute */
cr.save () ;
cr.set_line_width (2.5 * cr.get_line_width ()) ;
cr.move_to (x, y) ;
cr.line_to (x + radius / 2 * Math.sin (Math.PI / 6 * hours
+ Math.PI / 360 * minutes),
y + radius / 2 * -Math.cos (Math.PI / 6 * hours
+ Math.PI / 360 * minutes));
cr.stroke ();
cr.restore ();
// minute hand:
// the minute hand is rotated 6 degrees (pi/30 r) per minute
cr.move_to (x, y);
cr.line_to (x + radius * 0.75 * Math.sin (Math.PI / 30 * minutes),
y + radius * 0.75 * -Math.cos (Math.PI / 30 * minutes));
cr.stroke ();
// seconds hand:
// operates identically to the minute hand
cr.save ();
cr.set_source_rgb (1, 0, 0); // red
cr.move_to (x, y);
cr.line_to (x + radius * 0.7 * Math.sin (Math.PI / 30 * seconds),
y + radius * 0.7 * -Math.cos (Math.PI / 30 * seconds));
cr.stroke ();
cr.restore ();
return false ;
}
public override bool button_press_event (Gdk.EventButton event) {
var minutes = this.time.minute + this.minute_offset;
// From
// http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
var px = event.x - get_allocated_width () / 2;
var py = get_allocated_height () / 2 - event.y;
var lx = Math.sin (Math.PI / 30 * minutes);
var ly = Math.cos (Math.PI / 30 * minutes);
var u = lx * px + ly * py;
// on opposite side of origin
if (u < 0) {
return false;
}
var d2 = Math.pow (px - u * lx, 2) + Math.pow (py - u * ly, 2);
if (d2 < 25) { // 5 pixels away from the line
this.dragging = true;
print ("got minute hand\n");
}
return false;
}
public override bool button_release_event (Gdk.EventButton event) {
if (this.dragging) {
this.dragging = false;
emit_time_changed_signal ((int) event.x, (int) event.y);
}
return false;
}
public override bool motion_notify_event (Gdk.EventMotion event) {
if (this.dragging) {
emit_time_changed_signal ((int) event.x, (int) event.y);
}
return false;
}
private void emit_time_changed_signal (int x, int y) {
// decode the minute hand
// normalise the coordinates around the origin
x -= get_allocated_width () / 2;
y -= get_allocated_height () / 2;
// phi is a bearing from north clockwise, use the same geometry as
// we did to position the minute hand originally
var phi = Math.atan2 (x, -y);
if (phi < 0) {
phi += Math.PI * 2;
}
var hour = this.time.hour;
var minute = (int) (phi * 30 / Math.PI);
// update the offset
this.minute_offset = minute - this.time.minute;
redraw_canvas ();
time_changed (hour, minute);
}
private bool update () {
// update the time
this.time = Time.local (time_t ());
redraw_canvas ();
return true; // keep running this event
}
private void redraw_canvas () {
var window = get_window ();
if (null == window) {
return;
}
var region = window.get_clip_region ();
// redraw the cairo canvas completely by exposing it
window.invalidate_region (region, true);
window.process_updates (true);
}
static int main (string[] args) {
Gtk.init (ref args);
var window = new Window ();
var clock = new ClockWidget ();
window.add (clock);
window.destroy.connect (Gtk.main_quit);
window.show_all ();
Gtk.main ();
return 0;
}
}