1. CustomJTabbedPaneUI之程式範例
public class CustomJTabbedPaneUI extends JTabbedPane { String[] imgPath = null; public CustomJTabbedPaneUI() {} public CustomJTabbedPaneUI(String[] imgPath) { this.imgPath = imgPath; } @Override public void addTab(String title, final Component content) { JPanel tab = new JPanel(new BorderLayout()); JLabel label = new JLabel(title); label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 4)); JButton button = new CloseButton(imgPath); button.setBorder(BorderFactory.createEmptyBorder()); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { removeTabAt(indexOfComponent(content)); } }); tab.add(label, BorderLayout.WEST); tab.add(button, BorderLayout.EAST); tab.setOpaque(false); tab.setBorder(BorderFactory.createEmptyBorder(2, 1, 1, 1)); super.addTab(title, content); setTabComponentAt(getTabCount() - 1, tab); } }
2. CloseButton之程式範例
// 客製 關閉頁籤 的按鈕內容 class CloseButton extends JButton implements MouseListener { String[] imgPath = null; public CloseButton(String[] imgPath) { this.imgPath = imgPath; int size = 17; setPreferredSize(new Dimension(size, size)); setToolTipText("關閉頁籤"); setUI(new BasicButtonUI()); setContentAreaFilled(false); setFocusable(false); setBorder(BorderFactory.createEtchedBorder()); setBorderPainted(false); addMouseListener(this); setRolloverEnabled(true); } protected void paintComponent(Graphics g) { super.paintComponent(g); // 如無圖片,則利用繪圖的方式繪製出來 Graphics2D g2 = (Graphics2D) g.create(); if(imgPath == null) { if (getModel().isPressed()) { g2.translate(1, 1); } g2.setStroke(new BasicStroke(3)); g2.setColor(Color.BLACK); if (getModel().isRollover()) { g2.setColor(Color.RED); } g2.drawLine(5, 5, 12, 12); g2.drawLine(12, 6, 6, 12); g2.dispose(); } else { ImageIcon img, imgEntered, imgPressed; int size = imgPath.length; if(size == 3) { img = new ImageIcon(this.getClass().getResource(imgPath[0])); imgEntered = new ImageIcon(this.getClass().getResource(imgPath[1])); imgPressed = new ImageIcon(this.getClass().getResource(imgPath[2])); } else if(size == 2) { img = new ImageIcon(this.getClass().getResource(imgPath[0])); imgEntered = new ImageIcon(this.getClass().getResource(imgPath[1])); imgPressed = imgEntered; } else { img = new ImageIcon(this.getClass().getResource(imgPath[0])); imgEntered = img; imgPressed = img; } if (getModel().isRollover()) { g2.drawImage(imgEntered.getImage(), 1, 2, null, this); } else if(getModel().isPressed()) { g2.drawImage(imgPressed.getImage(), 1, 2, null, this); } else { g2.drawImage(img.getImage(), 1, 1, null, this); } g2.dispose(); } } @Override public void mouseClicked(MouseEvent e) {} @Override public void mousePressed(MouseEvent e) {} @Override public void mouseReleased(MouseEvent e) {} @Override public void mouseEntered(MouseEvent e) { Component component = e.getComponent(); if (component instanceof AbstractButton) { AbstractButton button = (AbstractButton) component; button.setBorderPainted(true); } } @Override public void mouseExited(MouseEvent e) { Component component = e.getComponent(); if (component instanceof AbstractButton) { AbstractButton button = (AbstractButton) component; button.setBorderPainted(false); } } }
3. 主程式範例
public void createAndShowGUI() { // 1.設置頁籤關閉按鈕之圖片來源 //private final CustomJTabbedPaneUI tab = new CustomJTabbedPaneUI(); // 無圖片版本 String[] imgPath = {"/test2/Res/btnClose.png", "/test2/Res/btnClose_Entered.png", "/test2/Res/btnClose_Pressed.png"}; // 有圖片版本 // 2.建立 JFrame JFrame frame = new JFrame("如何在JTabbedPane頁籤上增加關閉之按鈕"); frame.setLayout(new BorderLayout()); // 3.設置 Title JLabel labTitle = new JLabel(" 在JTabbedPane頁籤上增加關閉之按鈕"); labTitle.setPreferredSize(new Dimension(600, 50)); labTitle.setFont(new java.awt.Font("微軟正黑體", 1, 16)); frame.getContentPane().add(labTitle, BorderLayout.NORTH); // 4.設置 頁籤內容 CustomJTabbedPaneUI tabPane = new CustomJTabbedPaneUI(imgPath); tabPane.addTab("第一個頁籤", new JLabel("第一個頁籤")); tabPane.addTab("第二個頁籤*第二個頁籤", new JLabel("第二個頁籤*第二個頁籤")); tabPane.addTab("第三個頁籤/第三個頁籤/第三個頁籤", new JScrollPane(new JTree())); tabPane.setSelectedIndex(2); // 預設顯示第三個頁籤之內容 tabPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); // 頁籤滿時,多出往前往後之按鈕,以防頁籤變成上下擠之樣貌 frame.getContentPane().add(tabPane, BorderLayout.CENTER); // 5.設置 增加頁籤 與 關閉全部頁籤 之 Menu JPopupMenu popMenu = new JPopupMenu(); popMenu.add(new NewTabAction("增加頁籤", tabPane)); popMenu.addSeparator(); popMenu.add(new CloseAllAction("關閉全部頁籤", tabPane)); tabPane.setComponentPopupMenu(popMenu); // 6.設置 JFrame 基本設定 frame.setPreferredSize(new Dimension(600, 550)); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); }
▲主程式之程式
// 增加頁籤 之 Action private int count = 4; class NewTabAction extends AbstractAction { CustomJTabbedPaneUI tabPane = null; protected NewTabAction(String label, CustomJTabbedPaneUI tabPane) { super(label); this.tabPane = tabPane; } @Override public void actionPerformed(ActionEvent e) { if(tabPane != null) { tabPane.addTab("第" + count + "個頁籤", new JLabel("我是內容" + count)); tabPane.setSelectedIndex(tabPane.getTabCount() - 1); count++; } } }
▲增加頁籤 之 Action
// 關閉全部頁籤 之 Action class CloseAllAction extends AbstractAction { CustomJTabbedPaneUI tabPane = null; protected CloseAllAction(String label, CustomJTabbedPaneUI tabPane) { super(label); this.tabPane = tabPane; } @Override public void actionPerformed(ActionEvent e) { if(tabPane != null) { tabPane.removeAll(); } } }
▲關閉全部頁籤 之 Action
4. 執行結果
▲生成時之樣貌
▲移入關閉按鈕之圖片變動與提示文字
▲按下關閉按鈕之圖片變動
▲關閉該頁籤之樣貌
▲新增頁籤Meun與執行後之樣貌
▲關閉全部頁籤Meun與執行後之樣貌
參考網址:
http://ateraimemo.com/Swing/TabWithCloseButton.html
http://www.myjavazone.com/2011/02/jtabbedpane-con-x.html