Java GUI绘制时钟

Java GUI组件练习用Demo,主要是为了学习GUI的设计思路、组件的特性。这里的代码并不是最优雅的解决方案,千万别纠结这个……

 

要点:

  1. 绘图的框架应该继承自JFrame,具体组件继承自JPanel。
  2. 继承自JPanel的类覆写父类(JComponent)的paintComponent()方法,注意不是Container的paintComponents()!
  3. 这些都是不能重用的组件,所以要刷新则调用repaint(),此处在每次调用setter方法的时候进行调用。
  4. 通过时分秒计算时针、分针、秒针的位置需要用三角函数的知识。 
  5. 在计算时针和分针角度时,秒数对其影响太小(为second/3600),故此处为方便忽略不算。

 

效果图:黄线只是为了调整时钟数字摆放的位置,展示的代码中已经删去。

Java GUI绘制时钟_第1张图片

 

用于显示GUI的类,继承了JFrame,引用了两个继承自JPanel的类(分别用作绘画时钟和显示具体时间)。

package thinkwise.gui.graphics.practice;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.Timer;

public class DisplayClock extends JFrame {
	private StillClock clock = new StillClock();

	public DisplayClock() {
		
		final MessagePanel p = new MessagePanel(clock.getHour() + ":" + clock.getMinute() + ":" + clock.getSecond());
		p.setCentered(true);
		p.setFont(new Font("Courier", Font.BOLD, 16));
		p.setForeground(Color.blue);
		
		add(clock);
		add(p, BorderLayout.SOUTH);
		
		Timer timer = new Timer(1000, new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				clock.setCurrentTime();
				clock.repaint();
				p.setMessage(clock.getHour() + ":" + clock.getMinute() + ":" + clock.getSecond());
				p.repaint();
			}
		});
		timer.start();
		
	}
	
	public static void main(String[] args) {
		DisplayClock c = new DisplayClock();
		c.setTitle("Clock");
		c.setSize(300, 350);
		c.setVisible(true);
		c.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		c.setLocationRelativeTo(null);
	}
}

 

 时钟类

package thinkwise.gui.graphics.practice;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.Calendar;
import java.util.GregorianCalendar;

import javax.swing.JPanel;

public class StillClock extends JPanel {
	
	private int hour;
	private int minute;
	private int second;
	
	public StillClock() {
		setCurrentTime();
	}
	
	public StillClock(int hour, int minute, int second){
		this.hour = hour;
		this.minute = minute;
		this.second = second;
	}

	@Override
	public Dimension getPreferredSize() {
		return new Dimension(200, 200);
	}
	
	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		
		int xCenter = getWidth()/2;
		int yCenter = getHeight()/2;
		int clockRadius = (int) (Math.min(getWidth(), getHeight()) * 0.8 * 0.5);
		
		g.setColor(Color.black);
		g.drawOval(xCenter - clockRadius, yCenter - clockRadius, 2 * clockRadius, 2 * clockRadius);
		g.drawString("12", xCenter - 5, yCenter - clockRadius + 12);
		g.drawString("3", xCenter + clockRadius - 10, yCenter + 3);
		g.drawString("6", xCenter - 3, yCenter + clockRadius - 3);
		g.drawString("9", xCenter - clockRadius + 3, yCenter + 3);
		
		int sLength = (int) (clockRadius * 0.8);
		int xSecnd = (int) (xCenter + sLength * Math.sin(2 * Math.PI/60 * second));
		int ySecond = (int) (yCenter - sLength * Math.cos(2 * Math.PI/60 * second));
		g.setColor(Color.RED);
		g.drawLine(xCenter, yCenter, xSecnd, ySecond);
		
		int mLength = (int) (clockRadius * 0.65);
		int xMinute = (int) (xCenter + mLength * Math.sin((minute + second/60) * 2 * Math.PI/60));
		int yMinute = (int) (yCenter - mLength * Math.cos((minute + second/60) * (2 * Math.PI/60)));
		g.setColor(Color.blue);
		g.drawLine(xCenter, yCenter, xMinute, yMinute);
		
		int hLength = (int) (clockRadius * 0.5);
		int xHour = (int) (xCenter + hLength * Math.sin((hour % 12 + minute/60) * (2 * Math.PI/12)));
		int yHour = (int) (yCenter - hLength * Math.cos((hour % 12 + minute/60) * (2 * Math.PI/12)));
		g.setColor(Color.green);
		g.drawLine(xCenter, yCenter, xHour, yHour);
	}
	
	public void setCurrentTime(){
		Calendar calendar = new GregorianCalendar();
		this.hour = calendar.get(Calendar.HOUR_OF_DAY);
		this.minute = calendar.get(Calendar.MINUTE);
		this.second = calendar.get(Calendar.SECOND);
	}

	public int getHour() {
		return hour;
	}

	public void setHour(int hour) {
		this.hour = hour;
		repaint();
	}

	public int getMinute() {
		return minute;
	}

	public void setMinute(int minute) {
		this.minute = minute;
		repaint();
	}

	public int getSecond() {
		return second;
	}

	public void setSecond(int second) {
		this.second = second;
		repaint();
	}
	
}

 

时间文本显示:

package thinkwise.gui.graphics.practice;

import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.util.Calendar;
import java.util.GregorianCalendar;

import javax.swing.JPanel;

public class MessagePanel extends JPanel {

	private String message = "Welcome to Java";
	private int xCoordinate = 20;
	private int yCoordinate = 20;
	private boolean centered;
	private int interval = 10;
	
	public MessagePanel() {
	}
	
	public MessagePanel(String message){
		this.message = message;
	}
	
	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		
		if(centered){
			FontMetrics fm = g.getFontMetrics();
			int stringWidth = fm.stringWidth(message);
			int stringAscent = fm.getAscent();
			
			xCoordinate = getWidth()/2 - stringWidth/2;
			yCoordinate = getHeight()/2 + stringAscent/2;
		}
		g.drawString(message, xCoordinate, yCoordinate);
	}
	
	@Override
	public Dimension getPreferredSize() {
		return new Dimension(200, 30);
	}
	
	public void moveLeft(){
		xCoordinate -= interval;
		repaint();
	}
	
	public void moveRight(){
		xCoordinate += interval;
		repaint();
	}
	
	public void moveUp(){
		yCoordinate += interval;
		repaint();
	}
	
	public void moveDown(){
		yCoordinate -= interval;
		repaint();
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
		repaint();
	}

	public int getxCoordinate() {
		return xCoordinate;
	}

	public void setxCoordinate(int xCoordinate) {
		this.xCoordinate = xCoordinate;
		repaint();
	}

	public int getyCoordinate() {
		return yCoordinate;
	}

	public void setyCoordinate(int yCoordinate) {
		this.yCoordinate = yCoordinate;
		repaint();
	}

	public boolean isCentered() {
		return centered;
	}

	public void setCentered(boolean centered) {
		this.centered = centered;
		repaint();
	}

	public int getInterval() {
		return interval;
	}

	public void setInterval(int interval) {
		this.interval = interval;
		repaint();
	}
}

 

  参考资料:
1.Java语言程序设计

你可能感兴趣的:(Java)