一、 实验目的和要求
本实验旨在通过实验,培养学生将JAVA 线程的相关知识点(包括线程调度,线程同步等)有机结合并加以综合应用,在实验中设计多线程程序的能力。
实验内容:设计和编写一个编写一个指针式时钟程序,应用线程实现时钟的走动。
二、实验代码
package think;
import java.util.*;
import java.awt.*;
import javax.swing.*;
public class java_exp_04clock
{ public static void main(String args[])
{
JFrame frame = new JFrame();
ClockPaint panel = new ClockPaint();
frame.add(panel);
frame.setTitle("时钟");
frame.setBounds(200,200,400,400);
frame.setBackground(Color.white);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
class ClockPaint extends JPanel implements Runnable //
{ //小时,分钟,秒
ClockPaint()
{ Thread t = new Thread(this); //创建线程
t.start(); //启动线程
}
private int h, m, s;
public void paintComponent(Graphics g)
{
int r, l, x1, y1;
int x = getWidth(); //根据面板大小画时钟
int y = getHeight();
r = (int) (Math.min(x, y) * 0.4); //时钟半径
x = x / 2; //圆心坐标
y = y / 2;
g.setColor(Color.WHITE);
g.fillOval(x - r, y - r, r * 2, r * 2); //画钟面圆
l = (int) (r * 0.9);
g.setColor(Color.BLACK);
for(int i = 0; i<60; i++) //画刻度
{
x1 = (int) (x + l * Math.sin(i * (2 * Math.PI / 60)));
y1 = (int) (y - l * Math.cos(i * (2 * Math.PI / 60)));
if(i%5 == 0)
g.fillOval(x1 - 3, y1 - 3, 6, 6);
else
g.fillOval(x1 - 1, y1 - 1, 2, 2);
}
l = (int) (r * 0.5); //时针长度
x1 = (int) (x + l * Math.sin((h % 12 + m / 60.0) * (2 * Math.PI / 12)));
y1 = (int) (y - l * Math.cos((h % 12 + m / 60.0) * (2 * Math.PI / 12)));
g.setColor(Color.BLUE);
g.drawLine(x, y, x1, y1); //画时针
l = (int) (r * 0.7); //分针长度
x1 = (int) (x + l * Math.sin(m * (2 * Math.PI / 60)));
y1 = (int) (y - l * Math.cos(m * (2 * Math.PI / 60)));
g.setColor(Color.GREEN);
g.drawLine(x, y, x1, y1); //画分针
l = (int) (r * 0.9); //秒针长度
x1 = (int) (x + l * Math.sin(s * (2 * Math.PI / 60)));
y1 = (int) (y - l * Math.cos(s * (2 * Math.PI / 60)));
g.setColor(Color.RED);
g.drawLine(x, y, x1, y1); //画秒针
}
public void run()
{ while(true)
{
try
{
Thread.sleep(1000); //线程休眠 1000ms 也就是 1s 运行一次
}
catch (Exception ex) {}
Calendar cal = new GregorianCalendar();
h = cal.get(Calendar.HOUR); //获取当前时
m = cal.get(Calendar.MINUTE); //获取当前分
s = cal.get(Calendar.SECOND); //获取当前秒
this.repaint(); //重绘图形
}
}
}
三、界面
四、实验小结
整体的思路:
*顶层框架里放入一个时钟布局,根据线程的调度,每隔1s获取当前的时间来改变时针分针秒针的长度来更新布局。
遇到的问题和解决的方法:
* 一开始思路不清晰,搜索了几个例子看了感觉有了点思路。所以,没有思路的时候,记得搜索!
* 布局:时针分针秒针的位置可以根据当前的时间转换成角度,再显示。
* 图形设置的优化:由于界面是可以调整的,所以时钟的圆心和半径是一个难点。解决的方案是寻找长宽里小的那一个,再设置为一半即可获得圆心,半径设置为其0.9倍即可。
* 优化:线程睡眠的时间程序里设置的是1000ms,其实可以改成比1000ms更小的数字。即表示,每隔多少ms更新一次。设置成1000ms正好,不浪费资源也正好满足了需求。