cc在使用Cairo时以256退出 使用Cairo; 使用Gtk; 使用油嘴滑舌; 公共类ClockWidget:DrawingArea{ 私人时间; 专用整数分钟偏移量; 私人拖拉; 公共信号失效时间_改变(整小时、整分钟); 公共时钟部件(){ 添加\

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

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);
更新();
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;
    }
}