Java Java Swing小技巧 製作一個動態的多頁標籤控件 文/蔡學鏞 -----box----- #程式1 package com.vantechsoft.gui; import javax.swing.*; import java.awt.*; public class FancyTabbedPane extends JTabbedPane { public FancyTabbedPane() { } public FancyTabbedPane(int tabPlacement, int tabLayoutPolicy) { super(tabPlacement, tabLayoutPolicy); } public FancyTabbedPane(int tabPlacement) { super(tabPlacement); } public void insertTabInSlowMotion(String title, Icon icon, final Component c, String tip, int index) { // 這部分稍後再說明 } public void removeTabInSlowMotion(final int index) { // 這部分稍後再說明 } } -----end----- -----box----- #程式2 if (index > this.getTabCount()) { // 如果index值太大,則設定成此FancyTabbedPane對象 // 所允許的最大值,亦即getTabCount(); index = this.getTabCount(); } int idx = this.getSelectedIndex(); // 紀錄最上層的Tage Page。 this.insertTab(title, icon, c, tip, index); if (this.getTabCount() == 1) { // 如果是第一個Tabe Page,則不使用「飛進來」的效果。 return; } -----end----- -----box----- #程式3 if (index <= idx) { // 插入的位置小於或等於目前的位置 idx ++ ; // 目前的位置往後順移一個位置 } this.setSelectedIndex(idx); -----end----- -----box----- #程式4 Thread thread = new Thread() { public void run() { final FancyTabbedPane tabbedPane = FancyTabbedPane.this; int tabPlacement = tabbedPane.tabPlacement; final Rectangle tabRect = tabbedPane.getUI().getTabBounds(tabbedPane, 0); final Graphics g = tabbedPane.getGraphics(); int w = tabbedPane.getWidth(); // 取得控件的寬 int h = tabbedPane.getHeight(); // 取得控件的高 if (tabPlacement == JTabbedPane.TOP || tabPlacement == JTabbedPane.BOTTOM) { // 如果Tab位於上方或下方 //,則Tab Page的高度是(控件的高度)減(Tab的高度) h -= tabRect.height; } else { // 如果Tab位於左邊或右邊,則Tab Page的寬度是(控件的寬度)減(Tab的寬度) w -= tabRect.width; } final Image tabPageImg = tabbedPane.createImage(w, h); Graphics tabPageImgG = tabPageImg.getGraphics(); // 把Tab Page的畫面畫到tabPageImg c.paint(tabPageImgG.create(0, 0, tabPageImg.getWidth(tabbedPane), tabPageImg.getHeight(tabbedPane))); // 為了控制移動的速度,免得受到CPU快慢的影響, // 所以使用timeStamp1(上一次)與timeStamp2(現在), // 兩者的差距越大,表示經過的時間越多,需要移動的pixel越多。 long timeStamp1 = 0; long timeStamp2 = System.currentTimeMillis(); if (tabPlacement == JTabbedPane.TOP) { // Tab位於TOP,所以由下往上移動 int y = tabbedPane.getHeight(); while (y > tabRect.height) { // 此迴圈(loop)會不斷地繪製,造成移動的視覺效果 try { g.drawImage(tabPageImg, 0, y, null); System.currentTimeMillis(); timeStamp1 = timeStamp2; timeStamp2 = System.currentTimeMillis(); int gap = (int)(timeStamp2 - timeStamp1)/2; y-= (gap); } catch (Exception ex) { } } } else if (tabPlacement == JTabbedPane.BOTTOM) { // 略 } else if (tabPlacement == JTabbedPane.LEFT) { // 略 } else { // 略 } // 最後,必須選擇剛剛插入的Tab Page tabbedPane.setSelectedComponent(c); } }; thread.start(); -----end----- -----box----- #程式5 if (index >= this.getTabCount()) { return; } if (this.getTabCount() == 1) { // 如果這是FancyTabbedPane內的唯一一個Tabe Page, // 則直接將此元件刪除,不需要「飛出去」的效果 this.remove(0); return; } final FancyTabbedPane tabbedPane = FancyTabbedPane.this; tabbedPane.setSelectedIndex(index); Component c = tabbedPane.getSelectedComponent(); final Image movingImg = c.createImage(c.getWidth(), c.getHeight()); Graphics movingImgG = movingImg.getGraphics(); c.paint(movingImgG); int newIndex = index