java視覺化程式設計實踐--桌面時鐘
阿新 • • 發佈:2018-11-01
定義六個類用於實現整個視覺化時鐘
Clock.java:時鐘類,聚合錶盤和3個指標物件,構成整個時鐘
Plate.java:錶盤類,用來顯示靜態的時鐘錶盤、刻度等內容
Arm.java:指標類,用來顯示時、分、秒指標
ClockComponent:視覺化時鐘元件類,時鐘的視覺化顯示,即整個時鐘介面的錶盤顯示。
ClockFrame:整個程式視窗類,用於顯示整個程式的視窗。
VisualClock:主程式類,用於程式的啟動。
主要的程式如下:
VisualClock:
import java.awt.EventQueue; import javax.swing.JFrame; /*頂層視窗 JFrame 內容區域包括 2 個部分,上方為時鐘的視覺化顯示,下方 為文字顯示,上方用 JComponent 元件實現,在其 paintComponent 方法中繪製, 下方用 JLabel 實現,可以採用 BorderLayout 佈局實現 */ //新增主程式類 public class VisualClock { public static void main(String[] args) { EventQueue.invokeLater(()->{ ClockFrame frame=new ClockFrame(); frame.setTitle("視覺化時鐘"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE ); frame.setVisible(true); }); } }
ClockFrame:
import java.awt.*; import java.text.DateFormat; import java.text.SimpleDateFormat; import javax.swing.*; import java.util.Date; //建立頂層視窗類 public class ClockFrame extends JFrame { private ClockComponent comp;//整個時鐘的顯示 private JLabel timeLabel;//時鐘的文字顯示 public ClockFrame() { setSize(500,400); setLayout(new BorderLayout()); comp=new ClockComponent(); add(comp, BorderLayout.CENTER); JPanel timeLabelPanel=new JPanel(); timeLabel=new JLabel(""+new Date()); timeLabelPanel.add(timeLabel); add(timeLabelPanel, BorderLayout.SOUTH); //建立定時器並通過start啟動定時器,每隔一秒根據當前系統生成的時間 //生成字串,將字串更新到timeLabel上,同時呼叫repaint方法重新整理comp顯示 new Timer(1000,event->{ Date date=new Date(); DateFormat format=new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss"); String time=format.format(date); timeLabel.setText(time); comp.repaint(); }).start(); } }
ClockComponent:
import javax.swing.*; import java.awt.*; import java.awt.geom.Rectangle2D; //新增視覺化時鐘元件類 public class ClockComponent extends JComponent { //時鐘的視覺化顯示,即整個時鐘介面的錶盤顯示 Clock clock,clock1; public ClockComponent(){ clock=new Clock(); clock1=new Clock(); } public void paintComponent(Graphics g){ Rectangle2D r=getBounds(); Graphics2D g2=(Graphics2D)g; clock.setRectangle(new Rectangle2D.Double(r.getX(),r.getY(),r.getWidth()/2,r.getHeight()));//通過 getBounds 方法獲得元件窗體的大小,並將期傳給 clock 物件,再間接傳遞給 plate 物件 clock1.setRectangle(new Rectangle2D.Double(r.getWidth()/2,r.getY(),r.getWidth()/2,r.getHeight())); clock.draw(g2);//Graphics2D物件也是由 clock 的 draw 方法傳遞給 plate 的 draw 方法,從而將錶盤繪製在Component 元件中。 clock1.draw1(g2); } }
Clock:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
public class Clock {
//時鐘類,聚合錶盤和3個指標物件,構成整個時鐘
private Plate plate;
private Arm hour,minute,second;
public Clock(){
plate=new Plate();//構造錶盤物件
//呼叫指標的建立與繪製
hour=new Arm(Arm.Type.HOUR);
minute=new Arm(Arm.Type.MINUTE);
second=new Arm(Arm.Type.SECOND);
hour.setColor(Color.red);
minute.setColor(Color.BLUE);
second.setColor(Color.green);
}
public void setRectangle(Rectangle2D rect){
plate.setRectangle(rect);//設定外界矩形大小
//plate.setRectangle(rect);
hour.setRectangle(rect);
minute.setRectangle(rect);
second.setRectangle(rect);
}
public void draw(Graphics2D g2){
plate.draw(g2);//繪製錶盤
hour.draw(g2);
minute.draw(g2);
second.draw(g2);
}
public void draw1(Graphics2D g2){
plate.draw(g2);//繪製錶盤
hour.draw1(g2);
minute.draw1(g2);
second.draw1(g2);
}
}
Plate:
import java.awt.*;
import java.awt.geom.*;
public class Plate {
//錶盤類,用來顯示靜態的時鐘錶盤、刻度等內容
public static final int LINE_LENGTH=9; //刻度長度
public static final float LINE_WIDTH=3.0f; //線寬
public static final int GAP=10; //保留和邊界的距離
private Color backgroundColor=Color.LIGHT_GRAY;
private Color lineColor=Color.BLACK;
private Color numColor=Color.RED; //不同物件的顏色
private Rectangle2D r; //控制錶盤大小的外接矩形
void setRectangle(Rectangle2D rect){
r=rect;
}
/*
Plate 類封裝了對錶盤的繪製,通過 draw 介面,將錶盤繪製在傳入的
Graphics2D 物件上,由於 Plate 本身無法確定錶盤的大小,需要從外部設定外接
矩形的引數。在程式執行過程中,視窗大小發生變化時,需要呼叫 setRectangle
介面重新設定矩形大小。
*/
void draw(Graphics2D g2) {
//外部傳入的繪製物件
double width=r.getWidth();//獲得錶盤外界矩形的寬
double height=r.getHeight();
double minValue=Math.min(width, height); //長寬最小值
double x=r.getX()+width/2;
double y=r.getY()+height/2; //中心點 x、y 座標
double radius=minValue/2-GAP; //計算半徑
Ellipse2D.Double ellipse=new Ellipse2D.Double(x-radius,y-radius,radius*2,radius*2);
g2.setColor(backgroundColor); //設定背景顏色
g2.fill(ellipse); //填充錶盤背景
g2.setColor(lineColor);
Stroke stroke=new BasicStroke(LINE_WIDTH); //設定線寬
g2.setStroke(stroke);
g2.draw(ellipse); //繪製錶盤邊框線
//g2.draw(new Line2D.Double(x-radius,y,x-radius+LINE_LENGTH,y));
//g2.draw(new Line2D.Double(x+radius,y,x+radius-LINE_LENGTH,y));
//g2.draw(new Line2D.Double(x,y-radius,x,y-radius+LINE_LENGTH));
//g2.draw(new Line2D.Double(x,y+radius,x,y+radius-LINE_LENGTH)); //繪製刻度線,還有刻度值、部分刻度線還沒有完成,需要繼續補充
for(int i=0;i<12;++i){//迴圈實現刻度線
double size=4;
if(i%3==0) size=8;
drawMark(g2,x,y,radius,size,i);
}
//刻度值3,6,9,12的輸出
g2.drawString("12", (int)x - 5, (int)y- (int)radius + 20);
g2.drawString("9", (int)x - (int)radius + 11, (int)y + 5);
g2.drawString("3", (int)x + (int)radius - 18, (int)y + 3);
g2.drawString("6", (int)x - 3, (int)y + (int)radius - 11);
}
private void drawMark(Graphics2D g2,double x,double y,double radius,double size,int index) {
double angle=90;
angle-=index*30;
double x1=x+radius*Math.cos(Math.PI*angle/180);
double y1=y-radius*Math.sin(Math.PI*angle/180);
radius-=size;
double x2=x+radius*Math.cos(Math.PI*angle/180);
double y2=y-radius*Math.sin(Math.PI*angle/180);
g2.draw(new Line2D.Double(x1, y1, x2, y2));
}
}
Arm:
import java.awt.geom.*;
import java.time.LocalTime;
import java.awt.*;
public class Arm {
//指標類,用來顯示時、分、秒指標
public enum Type{HOUR,MINUTE,SECOND}; //列舉型別,指標型別
private Type type; //指標型別
private Color armColor=Color.BLUE; //指標顏色
private Rectangle2D r; //外接矩形大小
public Arm(Type t){
type=t;
}
public void setRectangle(Rectangle2D rect){
r=rect;
}
public void setColor(Color c){
armColor=c;
}
public void draw(Graphics2D g2) {
LocalTime time=LocalTime.now(); //獲取系統當前時間
int h=time.getHour()%12;
int m=time.getMinute();
int s=time.getSecond();
double angle=90,size=0;
double x=r.getX()+r.getWidth()/2;
double y=r.getY()+r.getHeight()/2; //計算中心點
size=Math.min(r.getWidth()/2, r.getHeight()/2);
switch(type){ //根據指標型別、時間計算角度和長度
case HOUR:
angle=90-h*30-m/2;
size*=18.0/30;
break;
case MINUTE:
angle=90-m*6-s/10;
size*=20.0/30;
break;
case SECOND:
angle=90-s*6;
size*=23.0/30;
break;
}
g2.setColor(armColor);
//double x1=x+size*Math.cos(Math.PI*angle/180);
//double y1=y-size*Math.sin(Math.PI*angle/180); //計算末端座標
//g2.draw(new Line2D.Double(x, y, x1, y1));
//換成三角狀的指標
int[] xpoint=new int[5];
int[] ypoint=new int[5];
double angle1=angle-90;
double size1=size/10;
double size2=size/5;
double dy1=size1*Math.sin(Math.PI*angle1/180);
double dx1=size1*Math.cos(Math.PI*angle1/180);
xpoint[0]=(int)(x+dx1);
ypoint[0]=(int)(y-dy1);
double dy2=size*Math.sin(Math.PI*angle/180);
double dx2=size*Math.cos(Math.PI*angle/180);
xpoint[1]=(int)(x+dx2);
ypoint[1]=(int)(y-dy2);
xpoint[2]=(int)(x-dx1);
ypoint[2]=(int)(y+dy1);
double dy3=size2*Math.sin(Math.PI*angle/180);
double dx3=size2*Math.cos(Math.PI*angle/180);
xpoint[3]=(int)(x-dx3);
ypoint[3]=(int)(y+dy3);
xpoint[4]=xpoint[0];
ypoint[4]=ypoint[0];
Polygon poly=new Polygon(xpoint,ypoint,5);
g2.fillPolygon(poly);
final double radius=5;
Ellipse2D.Double ellipse=new Ellipse2D.Double(x-radius,y-radius,radius*2,radius*2);
g2.setColor(Color.BLACK);
g2.fill(ellipse); //繪製中心圓點
}
public void draw1(Graphics2D g2) {
LocalTime time=LocalTime.now(); //獲取系統當前時間
int h=time.getHour()%12-11;
int m=time.getMinute();
int s=time.getSecond();
double angle=90,size=0;
double x=r.getX()+r.getWidth()/2;
double y=r.getY()+r.getHeight()/2; //計算中心點
size=Math.min(r.getWidth()/2, r.getHeight()/2);
switch(type){ //根據指標型別、時間計算角度和長度
case HOUR:
angle=90-h*30-m/2;
size*=18.0/30;
break;
case MINUTE:
angle=90-m*6-s/10;
size*=20.0/30;
break;
case SECOND:
angle=90-s*6;
size*=23.0/30;
break;
}
g2.setColor(armColor);
//double x1=x+size*Math.cos(Math.PI*angle/180);
//double y1=y-size*Math.sin(Math.PI*angle/180); //計算末端座標
//g2.draw(new Line2D.Double(x, y, x1, y1));
//換成三角狀的指標
int[] xpoint=new int[5];
int[] ypoint=new int[5];
double angle1=angle-90;
double size1=size/10;
double size2=size/5;
double dy1=size1*Math.sin(Math.PI*angle1/180);
double dx1=size1*Math.cos(Math.PI*angle1/180);
xpoint[0]=(int)(x+dx1);
ypoint[0]=(int)(y-dy1);
double dy2=size*Math.sin(Math.PI*angle/180);
double dx2=size*Math.cos(Math.PI*angle/180);
xpoint[1]=(int)(x+dx2);
ypoint[1]=(int)(y-dy2);
xpoint[2]=(int)(x-dx1);
ypoint[2]=(int)(y+dy1);
double dy3=size2*Math.sin(Math.PI*angle/180);
double dx3=size2*Math.cos(Math.PI*angle/180);
xpoint[3]=(int)(x-dx3);
ypoint[3]=(int)(y+dy3);
xpoint[4]=xpoint[0];
ypoint[4]=ypoint[0];
Polygon poly=new Polygon(xpoint,ypoint,5);
g2.fillPolygon(poly);
final double radius=5;
Ellipse2D.Double ellipse=new Ellipse2D.Double(x-radius,y-radius,radius*2,radius*2);
g2.setColor(Color.BLACK);
g2.fill(ellipse); //繪製中心圓點
}
}
最後可以在Eclipse中建立一個包檔案,將這些類放入其中即可。
程式執行結果如下:
兩個時鐘:第一個是中國時間,第二個是美國紐約時間
如果只想在介面中顯示一個時鐘的話,直接在ClockComponent類中刪除一個時鐘定義即可。
做這個時鐘介面時發現一個實現的比較基礎的視覺化時鐘程式,感覺也挺好的:
https://blog.csdn.net/qq_24653023/article/details/52195190