使用Swing繪制動(dòng)態(tài)時(shí)鐘
本文實(shí)例為大家分享了利用Swing繪制一個(gè)動(dòng)態(tài)時(shí)鐘的具體代碼,供大家參考,具體內(nèi)容如下
效果
代碼在下面,可跳過(guò)解析。
前言
編程實(shí)現(xiàn)一個(gè)時(shí)鐘
利用Swing繪制一個(gè)時(shí)鐘,只能是靜態(tài)的。利用Calendar類獲取當(dāng)前的時(shí)分秒,然后根據(jù)數(shù)學(xué)公式繪制相應(yīng)的時(shí)鐘就可以了。
如果靜態(tài)的時(shí)鐘已經(jīng)足夠你使用,那么就無(wú)須用到線程的概念。
如何讓時(shí)鐘“動(dòng)起來(lái)”
當(dāng)然了,動(dòng)起來(lái)肯定是不可能的,但是我們可以利用人眼的視覺(jué),讓時(shí)鐘“好像動(dòng)起來(lái)”,其實(shí)著很簡(jiǎn)單,只要讓當(dāng)前的圖像每隔一秒種刷新一次就可以了。這樣秒針在動(dòng),數(shù)字時(shí)間也在動(dòng),整個(gè)時(shí)鐘就好像“動(dòng)起來(lái)了”
線程
利用線程實(shí)現(xiàn)刷新,刷新間隔是1秒,每次刷新都先生成當(dāng)前的時(shí)間,然后JVM又會(huì)自動(dòng)調(diào)用paintComponent方法繪制圖形,這樣就好像時(shí)鐘動(dòng)起來(lái)了。
Thread thread = new Thread(){
public void run(){
while(true){
StillClock clock = new StillClock();
MessagePanel messagePanel1=new MessagePanel(clock.getHour()+":"+
clock.getMinute()+":"+clock.getSecond());
//設(shè)置顯示居中
messagePanel1.setCentered(true);
//設(shè)置前景顏色
messagePanel1.setForeground(Color.black);
//設(shè)置字體
messagePanel1.setFont(new Font("Courier",Font.BOLD,16));
add(clock);
add(messagePanel1,BorderLayout.SOUTH);
clock.setVisible(true);
validate(); //接下來(lái)會(huì)每隔一秒重繪一次時(shí)鐘——即(從frame中將clock組件刪除),因此調(diào)用validate方法,使容器重新布置其子組件
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
clock.setVisible(false);
remove(clock); //在父容器中將其刪除
clock.invalidate(); //使容器失效
}
}
};
thread.start();
線程代碼解析
Thread thread = new Thread(){};
注意結(jié)尾使用了分號(hào),既然使用了線程,那么需要重寫它的run方法:
public void run(){}
既然想讓時(shí)鐘一直動(dòng)起來(lái),那么死循環(huán)是最好的選擇
while(true){}
在while里面,每次都先生成當(dāng)前的時(shí)間:
StillClock clock = new StillClock();
這里生成了一個(gè)無(wú)參構(gòu)造的StillClock類,StillClock的無(wú)參構(gòu)造方法里面會(huì)自動(dòng)生成當(dāng)前的時(shí)間。
注意:這里的StillClock是我自己定義的,代碼貼在后面,但是如果不關(guān)心他是怎么實(shí)現(xiàn)的,可以直接忽略原理,直接使用,包括代碼里面的messagePanel也是一樣的自定義類。
時(shí)間生成完了之后,把時(shí)鐘圖形、當(dāng)前時(shí)間的字符串、布局位置利用add()方法繪制到屏幕上
add(clock); add(messagePanel1,BorderLayout.SOUTH);
接下來(lái)會(huì)每隔一秒重繪一次時(shí)鐘——即(從frame中將clock組件刪除),因此調(diào)用validate方法,使容器重新布置其子組件。
thread.start();
讓線程開始工作把。
完整代碼
DisplayClock.java:
package Test;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
public class DisplayClock extends JFrame {
public DisplayClock(){
//創(chuàng)建一個(gè)現(xiàn)在的時(shí)間
StillClock clock=new StillClock();
//獲取當(dāng)前的時(shí)間
clock.setCurrentTime();
//設(shè)置時(shí)間的顯示格式
Thread thread = new Thread(){
public void run(){
while(true){
StillClock clock = new StillClock();
MessagePanel messagePanel1=new MessagePanel(clock.getHour()+":"+
clock.getMinute()+":"+clock.getSecond());
//設(shè)置顯示居中
messagePanel1.setCentered(true);
//設(shè)置前景顏色
messagePanel1.setForeground(Color.black);
//設(shè)置字體
messagePanel1.setFont(new Font("Courier",Font.BOLD,16));
add(clock);
add(messagePanel1,BorderLayout.SOUTH);
clock.setVisible(true);
validate(); //接下來(lái)會(huì)每隔一秒重繪一次時(shí)鐘——即(從frame中將clock組件刪除),因此調(diào)用validate方法,使容器重新布置其子組件
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
clock.setVisible(false);
remove(clock); //在父容器中將其刪除
clock.invalidate(); //使容器失效
}
}
};
thread.start();
//布局默認(rèn)為BorderLayout,讓顯示信息在底部(即南邊)
}
public static void main(String[] args) {
DisplayClock frame=new DisplayClock();
frame.setTitle("DisplayClock");
frame.setSize(300,350);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
StillClock.java:
package Test;
import sun.util.calendar.Gregorian;
import javax.swing.*;
import java.awt.*;
import java.util.Calendar;
import java.util.GregorianCalendar;
public class StillClock extends JPanel {
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();
}
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;
}
//使用Graphics類繪制圖形,需要重寫paintComponent方法
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//繪制時(shí)鐘參數(shù)
int clockRadius=(int)(Math.min(getWidth(),getHeight())*0.8*0.5);
int xCenter=getWidth()/2;
int yCenter=getHeight()/2;
//繪制一個(gè)圓
g.setColor(Color.BLACK);
g.drawOval(xCenter-clockRadius,yCenter-clockRadius,2*clockRadius
,2*clockRadius);
g.drawString("12",xCenter-5,yCenter-clockRadius+12);
g.drawString("9",xCenter-clockRadius+3,yCenter+5);
g.drawString("3",xCenter+clockRadius-10,yCenter
+3);
g.drawString("6",xCenter-3,yCenter+clockRadius-3);
//繪制秒針
int sLength=(int)(clockRadius*0.8);
int xSecond=(int)(xCenter+sLength*Math.sin(second*(2*Math.PI/60)));
int ySecond=(int)(xCenter-sLength*Math.cos(second*(2*Math.PI/60)));
g.setColor(Color.red);
g.drawLine(xCenter,yCenter,xSecond,ySecond);
//繪制分針
int mLength=(int)(clockRadius*0.65);
int xMinute=(int)(xCenter+mLength*Math.sin(minute*(2*Math.PI/60)));
int yMinute=(int)(xCenter-mLength*Math.cos(minute*(2*Math.PI/60)));
g.setColor(Color.blue);
g.drawLine(xCenter,yCenter,xMinute,yMinute);
//繪制時(shí)針
int hLength=(int)(clockRadius*0.5);
int xHour=(int)(xCenter+hLength*Math.sin((hour%12+minute/60.0)*(2*Math.PI/12)));
int yHour=(int)(xCenter-hLength*Math.cos((hour%12+minute/60.0)*(2*Math.PI/12)));
g.setColor(Color.green);
g.drawLine(xCenter,yCenter,xHour,yHour);
}
public void setCurrentTime(){
//構(gòu)造一個(gè)日歷類設(shè)定當(dāng)前日期和時(shí)間
Calendar calendar=new GregorianCalendar();
//設(shè)定時(shí)分秒
this.hour=calendar.get(Calendar.HOUR_OF_DAY);
this.minute=calendar.get(Calendar.MINUTE);
this.second=calendar.get(Calendar.SECOND);
}
public Dimension getPreferredSize(){
return new Dimension(200,200);
}
}
messagePanel:
package Test;
import javax.swing.*;
import java.awt.*;
public class MessagePanel extends JPanel {
//顯示的信息
private String message="Welcome to java";
//顯示信息x的坐標(biāo)
private int xCoordinate=20;
//顯示信息y的坐標(biāo)
private int yCoordinate=20;
//信息是否被顯示在中心部位
private boolean centered;
//水平和垂直的移動(dòng)顯示信息
private int interval=10;
public int getXCoordinate() {
return xCoordinate;
}
public void setXCoordinate(int xCoordinate) {
this.xCoordinate = xCoordinate;
repaint();
}
//無(wú)參構(gòu)造
public MessagePanel() {
}
//帶參構(gòu)造
public MessagePanel(String message) {
this.message = message;
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();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if(centered){
//設(shè)定字體
FontMetrics fm=g.getFontMetrics();
//設(shè)置顯示字體
int stringWidth=fm.stringWidth(message);
int stringAscent=fm.getAscent();
xCoordinate=getWidth()/2-stringWidth/2;
yCoordinate=getHeight()/2+stringAscent/2;
}
g.drawString(message,xCoordinate,yCoordinate);
}
//讓信息往左邊移動(dòng)
public void moveLeft(){
xCoordinate-=interval;
repaint();
}
//讓信息往右邊移動(dòng)
public void moveRight(){
xCoordinate+=interval;
repaint();
}
//讓信息向上移動(dòng)
public void moveUp(){
yCoordinate+=interval;
repaint();
}
public void moveDown(){
yCoordinate-=interval;
repaint();
}
//固定寫法,不必探究
@Override
public Dimension getPreferredSize() {
return new Dimension(200,30);
}
}
結(jié)束
寫的有些粗糙,有需要的可以根據(jù)自己的需求進(jìn)行更改,比如如何更加穩(wěn)定的實(shí)現(xiàn)動(dòng)態(tài)時(shí)鐘,讓時(shí)鐘刻度更加精細(xì)(根據(jù)數(shù)學(xué)公式增加刻度線即可),希望可以幫助到你。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。
上一篇:springboot實(shí)現(xiàn)文件上傳步驟解析
欄 目:Java
下一篇:如何解決線程太多導(dǎo)致java socket連接池出現(xiàn)的問(wèn)題
本文標(biāo)題:使用Swing繪制動(dòng)態(tài)時(shí)鐘
本文地址:http://www.jygsgssxh.com/a1/Java/8930.html
您可能感興趣的文章
- 01-10Springboot中@Value的使用詳解
- 01-10JAVA8獨(dú)有的map遍歷方式(非常好用)
- 01-10SpringBoot使用RabbitMQ延時(shí)隊(duì)列(小白必備)
- 01-10Java使用Scanner類進(jìn)行控制臺(tái)輸入實(shí)現(xiàn)方法
- 01-10springboot2.0使用Hikari連接池的方法(替換druid)
- 01-10mybatis if標(biāo)簽使用總結(jié)
- 01-10Spring實(shí)戰(zhàn)之使用@POSTConstruct和@PreDestroy定制生命周期行為操作示例
- 01-10如何基于Spring使用工廠模式實(shí)現(xiàn)程序解耦
- 01-10SpringBoot使用Redisson實(shí)現(xiàn)分布式鎖(秒殺系統(tǒng))
- 01-10Spring實(shí)戰(zhàn)之使用@Resource配置依賴操作示例


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10Java實(shí)現(xiàn)動(dòng)態(tài)模擬時(shí)鐘
- 01-10Springboot中@Value的使用詳解
- 01-10JavaWeb實(shí)現(xiàn)郵件發(fā)送功能
- 01-10利用Java實(shí)現(xiàn)復(fù)制Excel工作表功能
- 01-10Java實(shí)現(xiàn)動(dòng)態(tài)數(shù)字時(shí)鐘
- 01-10java基于poi導(dǎo)出excel透視表代碼實(shí)例
- 01-10java實(shí)現(xiàn)液晶數(shù)字字體顯示當(dāng)前時(shí)間
- 01-10基于Java驗(yàn)證jwt token代碼實(shí)例
- 01-10Java動(dòng)態(tài)顯示當(dāng)前日期和時(shí)間
- 01-10淺談Java中真的只有值傳遞么
隨機(jī)閱讀
- 01-10delphi制作wav文件的方法
- 04-02jquery與jsp,用jquery
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改


