這個簡單的Java計時器和Java數字時鐘的原理差不多,都是利用Java的Timer做計時,然后根據當前的時間生成需要顯示的圖片或者文字,通過重寫paintComponent方法呈現在界面上.
先看看效果:
基本的工程目錄結構如下:
其中MissionTimerPanel是主要的類,它主要提供了計時器顯示數字的繪制,計時器背景的繪制,計時器閃爍的點的繪制,同時使用Swing的Timer使界面的時間發生改變,最終調用Java的重繪,通過paintComponent方法刷新界面.
先寫一下它的繼承關系:
publicclass MissionTimerPanel extends JPanel implements
ActionListener, MouseListener {
看一下它的主要屬性字段:
/** the image of number 0~9 */
privatefinal BufferedImage[] DIGIT_ARRAY = { createDigit(0),
createDigit(1), createDigit(2), createDigit(3),
createDigit(4), createDigit(5), createDigit(6), createDigit(7), createDigit(8),
createDigit(9) };
/** the image of the dots display */
privatefinal BufferedImage DOTS_ON = createDots(true);
/** the image of the dots disappear */
privatefinal BufferedImage DOTS_OFF = createDots(false);
/** the image of panel background */
privatefinal BufferedImage BACKGROUND_IMAGE = createBackground(450, 180);
/** mission timer */
privatefinal Timer TIMER = new Timer(500, this);
分別定義了數字的圖片,點的圖片,背景圖片和Timer.
通過構造函數設置大小和增加鼠標監聽:
public MissionTimerPanel() {
setPreferredSize(new Dimension(450, 180));
setSize(new Dimension(450, 180));
addMouseListener(this);
}
然后是繪制數字的方法
// create digit with given number.
private BufferedImage createDigit(int digit) {
首先通過Java的GraphicsEnvironment取得GraphicsConfiguration,創建圖片:
GraphicsConfiguration gfxConf = GraphicsEnvironment
.getLocalGraphicsEnvironment().getDefaultScreenDevice()
.getDefaultConfiguration();
BufferedImage IMAGE = gfxConf.createCompatibleImage(46, 65,
Transparency.TRANSLUCENT);
然后創建圖片的繪制樣式和上下文:
Graphics2D g2 = (Graphics2D) IMAGE.getGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_PURE);
g2.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_DITHERING,
RenderingHints.VALUE_DITHER_ENABLE);
g2.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
接著開始創建數字組成的線,每個數字組成都是8這個數字的一份,所以先繪制一下8所需要的所有線段:
GeneralPath segment_a = new GeneralPath();
segment_a.moveTo(17, 0);
segment_a.lineTo(38, 0);
segment_a.lineTo(37, 8);
segment_a.lineTo(16, 8);
segment_a.closePath();
這是其中一條,其它的也類似.
最后就是根據數字使用上面的線條繪制指定的圖片了:
case 2:
g2.setColor(COLOR_ON);
g2.fill(segment_a);
g2.fill(segment_b);
g2.fill(segment_d);
g2.fill(segment_e);
g2.fill(segment_g);
g2.setColor(COLOR_OFF);
g2.fill(segment_c);
g2.fill(segment_f);
g2.setColor(FRAME_COLOR_ON);
g2.draw(segment_a);
g2.draw(segment_b);
g2.draw(segment_d);
g2.draw(segment_e);
g2.draw(segment_g);
g2.setColor(FRAME_COLOR_OFF);
g2.draw(segment_c);
g2.draw(segment_f);
break;
這是2的繪制,其它的也類似,這樣就生成了所有的數字.
然后是繪制點的方法:
private BufferedImage
createDots(boolean on) {
它和繪制數字基本一致,也是通過Java的GraphicsEnvironment取得GraphicsConfiguration,創建圖片,然后創建圖片的繪制樣式和上下文,最后畫點:
g2.setColor(COLOR_ON);
g2.fillOval(8, 20, 7, 7);
g2.fillOval(5, 39, 7, 7);
g2.setColor(FRAME_COLOR_ON);
g2.drawOval(8, 20, 7, 7);
g2.drawOval(5,
39, 7, 7);
接著是繪制背景的顏色、字和圖片:
private BufferedImage
createBackground(int width, int height) {
前面創建圖片和設置樣式和繪制數字和點的基本一致,只是使用了LinearGradientPaint進行顏色漸變的繪制:
final LinearGradientPaint GRADIENT_HIGHLIGHT = new LinearGradientPaint(START_HIGHLIGHT,
STOP_HIGHLIGHT, FRACTIONS_HIGHLIGHT, COLORS_HIGHLIGHT);
g2.setPaint(GRADIENT_HIGHLIGHT);
g2.fillRect(17, 79, 176, 87);
g2.fillRect(193,
79, 239, 87);
最后把對應的顯示字繪制上:
g2.drawString("HOURS", 75, 65);
這樣所有的繪制圖片就結束了.
然后是處理組件的監聽:
@Override
publicvoid
mouseClicked(MouseEvent event) {
當鼠標點擊組件時啟動Timer,再次點擊終止Timer
if (event.getButton()
== MouseEvent.BUTTON1) {
if (TIMER.isRunning()) {
stopTimer();
} else {
startTimer();
}
if
(event.getClickCount() == 2) {
resetTimer();
}
}
啟動、啟動和重置Timer比較簡單,直接使用Timer的Start和Stop就可以了.
publicvoid startTimer() {
TIMER.start();
}
重置的話還要停止Timer后再刷新一次畫面.
再來就是Timer啟動后觸發的事件:
@Override
publicvoid
actionPerformed(ActionEvent event) {
在這里會根據計數設置當前應該顯示的圖片,最后調用repaint.
if (sec_right == 10) {
sec_right = 0;
sec_left++;
}
最后就是復寫paintComponent方法使組件更新了:
@Override
protectedvoid
paintComponent(Graphics g) {
首先取得繪制的上下文Graphics2D g2 = (Graphics2D) g.create();
然后設置繪制的屬性和樣式:
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_PURE);
g2.setRenderingHint(RenderingHints.KEY_DITHERING,
RenderingHints.VALUE_DITHER_ENABLE);
g2.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
設置好顏色、鋸齒、混合色、邊等屬性后就可以繪制了:
//背景的繪制
g2.drawImage(BACKGROUND_IMAGE, 0, 0, this);
//點的繪制
g2.drawImage(DOTS_ON, 172, 90, this);
//時分秒等的繪制
g2.drawImage(DIGIT_ARRAY[hour_left], 38, 90, this);
繪制完所有的時分秒、點之后,重寫就完成了.
因為這個組件就是一個Panel,可以和正常Panel一樣使用,通過new MissionTimerPanel();就可以調用了.