Hướng dẫn viết chương trình vẽ đồng hồ kim 2D bằng Java

Hiện tại, vì công việc quá bận rộn nên mình không còn thời gian để post bài và duy trì nội dung cho blog nữa. Do đó tại thời điểm này, mình quyết định ngừng phát triển blog. Mọi bài viết sẽ vẫn được lưu trữ và mình sẽ cố gắng hỗ trợ tất cả các bạn khi có comment hỏi. Cảm ơn các bạn đã ủng hộ blog suốt thời gian qua !


Ý tưởng rất đơn giản, dùng hàm fillOval để vẽ mặt đồng hồ, và dùng hàng drawLine để vẽ kim đồng hồ.

Ta vẽ một cái hình oval có 2 đường kính bằng nhau (tức là hình tròn), có tọa độ của đỉnh góc bên trái (chỗ 9 giờ trên mặt đồng hồ) là 50,50 và đường kính là 200 tức là tâm đường tròng có tọa độ là 50+(200/2) = 150.

Còn vẽ kim đồng hồ thì chỉ cần dùng hàm drawLine(x1,y1,x2,y2); trong đó x1 là hoành độ điểm đầu,y1 là tung độ điểm đầu, x2 là hoành độ điểm cuối.Với x1,y1 luôn bằng 150,150 là tâm hình tròn.


còn x2,y2 được tính với công thức sau:

Nếu là kim giây:

-Kim giây phải quay hết 1 đường tròn 360 độ qua 60 cái tíc, vậy 1 cái tích phải nhích 6 độ nhưng do tính bằng radian nên số độ phải

rKimGiay = (số giây * 6) * PI/180; (do 1 độ bằng Pi/180 radian);

x2 = x1 + (bán kính * cos(rKimGiay - Pi/2));




y2 = y1 + (bán kính * sin(rKimGiay - Pi/2));

(mình không hiểu rõ lượng giác lắm, nhưng khi vẽ nó bị lệch 90 nên mình trừ ra 1 cung pi/2 để nó chạy đúng)

Tương tự với kim phút, nhưng mình phải cộng thêm (số giây/60) để kim phút nhích khi kim giây nhích

rKimPhut = ((số phút + (số giây/60)) * 6) * PI/180;

Và với kim giờ thì mình làm giống kim phút nhưng phải *30 thay thì 6 vì mỗi nấc giờ, kim giờ nhích 1 góc 30 độ ( 30x12=360);

rKimGiờ = ((số giờ + (số phút/60)) * 30) * PI/180;

Còn giờ hiện hành thì mình sử dụng đối tượng GregorianCalendar để lấy giây,phút, giờ hiện hành



GregorianCalendar cal;
double second = cal.get(Calendar.SECOND);
double minute = cal.get(Calendar.MINUTE);
double hours = cal.get(Calendar.HOUR);


Code hoành chỉnh

package clock;

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;

/**
*
* @author hungnq
*/
public class Clock2d extends Applet {

GregorianCalendar cal;
Timer clockTimer = new Timer();
TimeZone clockTimeZone = TimeZone.getDefault();

public Clock2d() {
clockTimer.schedule(new TickTimerTask(), 0, 1000);
}

@Override
public void init() {
}

@Override
public void paint(Graphics g) {
g.setColor(Color.BLUE);
g.fillOval(40, 40, 220, 220);
g.setColor(Color.WHITE);
g.fillOval(50, 50, 200, 200);
//g.setColor(Color.ORANGE);
// g.fillOval(80, 80, 140, 140);
//g.drawOval(45,45, 210, 210);
double second = cal.get(Calendar.SECOND);
double minute = cal.get(Calendar.MINUTE);
double hours = cal.get(Calendar.HOUR);
//double milis = cal.get(Calendar.MILLISECOND);
//Vẽ mặt đồng hồ
for (int i = 0; i < 60; i++) {
int length = 90;
double rad = (i * 6) * (Math.PI) / 180;
if (i % 5 == 0) {
length = 82;
g.setColor(Color.BLUE);
} else {
g.setColor(Color.GRAY);
}
int x = 150 + (int) (95 * Math.cos(rad - (Math.PI / 2)));
int y = 150 + (int) (95 * Math.sin(rad - (Math.PI / 2)));
int x1 = 150 + (int) (length * Math.cos(rad - (Math.PI / 2)));
int y1 = 150 + (int) (length * Math.sin(rad - (Math.PI / 2)));
g.drawLine(x, y, x1, y1);
}
//vẽ kim đồng hồ
drawHands(g, second, minute, hours);
//g.fillOval(50, 50, 200, 200);
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss");
g.setColor(Color.BLUE);
g.setFont(new Font("Tahoma", Font.BOLD, 16));
g.drawString(sdf.format(cal.getTime()), 120, 20);
g.setFont(new Font("Arial", Font.BOLD, 10));
g.drawString("CODE BY HUNGNQ", 110, 140);
}

/***
* 1 độ = pi/180 rad
* -đường tròn 360 độ, kim giây phải nhích 60 lần suy ra 1 lần nhích số radian
* bằng (số giây * 6) * pi/180 rad
* -tương tự với số phút, nhưng khi kim giây nhích thì kim phút cũng phải nhích
* theo nên ta công thêm số giây/60 vào để kim phút nhích, ví dụ 1 phút 30 giây
*  thì bằng 1,5 phút
* - đối với kim giờ thì quay 1 vòng tròn là 12 giờ, vậy mỗi giờ tăng 1 góc
* là  số giờ x 30 (vì 12x30=360), và phải cộng thêm số phút để cho chính xác
* lưu ý phải trừ ra pi/2 rad để đồng hồ quay đúng, vì đường tròn lượng giác
* có chiều quay ngược kim đồng hồ tương ứng 9h=pi rad,12=pi/2 rad... nên phải trừ ra pi/2
* @param g
* @param second
* @param minute
* @param hours
*/
public void drawHands(Graphics g, double second, double minute, double hours) {
double rSecond = (second * 6) * (Math.PI) / 180;
double rMinute = ((minute + (second / 60)) * 6) * (Math.PI) / 180;
double rHours = ((hours + (minute / 60)) * 30) * (Math.PI) / 180;
g.setColor(Color.RED);
g.drawLine(150, 150, 150 + (int) (100 * Math.cos(rSecond - (Math.PI / 2))), 150 + (int) (100 * Math.sin(rSecond - (Math.PI / 2))));
g.setColor(Color.BLACK);
g.drawLine(150, 150, 150 + (int) (70 * Math.cos(rMinute - (Math.PI / 2))), 150 + (int) (70 * Math.sin((rMinute - (Math.PI / 2)))));
g.drawLine(150, 150, 150 + (int) (50 * Math.cos(rHours - (Math.PI / 2))), 150 + (int) (50 * Math.sin(rHours - (Math.PI / 2))));
//g.drawLine(150, 150, 150+(int)(100*Math.sin(2*Math.PI)),150+(int)(100*Math.cos(2*Math.PI)));
}

class TickTimerTask extends TimerTask {

@Override
public void run() {
//throw new UnsupportedOperationException("Not supported yet.");
cal = (GregorianCalendar) GregorianCalendar.getInstance(clockTimeZone);
repaint();
}
}

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
JFrame frame = new JFrame("Clock 2D");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(330, 330));
Clock2d clock2d = new Clock2d();
clock2d.setPreferredSize(new Dimension(320, 320));
clock2d.init();
frame.setLayout(new BorderLayout());
frame.getContentPane().add(clock2d, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
}
(Theo Bút chì số)
 

Web Design Technology blogs [ itdl ] Auto Backlink

HomeBlog ArchiveServicesLink2MeContactSubmit your PostPost RSS

Copyright © 2012 [ itdl ] Just for Share. Designed by Ngoc Luong - Freelancer

Best view in Chrome 11+, Firefox 5+ with resolution 1024 x 768 pixel. Powered by Blogger.