JTabbedPane 加close的两种方法(jdk1.5和1.6+)
JTabbedPane在1.6的时候新增了setTabComponentAt方法(http://docs.oracle.com/javase/tutorial/uiswing/components/tabbedpane.html),插入一个关闭按钮很方便,但是jdk1.6以下并不支持。找了两种能够支持关闭按钮的写法,第二种是从http://www.codeproject.com/Articles/18496/JTabbedPane-with-Closing-Tabs上拔下来,简单的改了下1.5应该可用。
NewJFrame.java
package org.javaweb.jrat.server.ui; /** * * @author yz */ public class NewJFrame extends javax.swing.JFrame { public NewJFrame() { initComponents(); } private void initComponents() { jPanel1 = new javax.swing.JPanel(); jTabbedPane1 = new javax.swing.JTabbedPane(); jScrollPane1 = new javax.swing.JScrollPane(); jTextArea1 = new javax.swing.JTextArea(); jScrollPane2 = new javax.swing.JScrollPane(); jTextArea2 = new javax.swing.JTextArea(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); jTextArea1.setColumns(20); jTextArea1.setRows(5); jScrollPane1.setViewportView(jTextArea1); jTabbedPane1.addTab("tab1", jScrollPane1); jTextArea2.setColumns(20); jTextArea2.setRows(5); jScrollPane2.setViewportView(jTextArea2); jTabbedPane1.addTab("tab2", jScrollPane2); jTabbedPane1.setTabComponentAt((jTabbedPane1.getComponentCount()-1)/2,new ButtonTabComponent(jTabbedPane1)); jTabbedPane1.setTabComponentAt((jTabbedPane1.getComponentCount()-1)/2,new ButtonTabComponent(jTabbedPane1)); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jTabbedPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jTabbedPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE) ); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); pack(); }// </editor-fold> /** * @param args the command line arguments */ public static void main(String args[]) { /* Create and display the form */ java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new NewJFrame().setVisible(true); } }); } // Variables declaration - do not modify private javax.swing.JPanel jPanel1; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JTabbedPane jTabbedPane1; private javax.swing.JTextArea jTextArea1; private javax.swing.JTextArea jTextArea2; // End of variables declaration }
TabbedPanel.java
import java.awt.BasicStroke; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.AbstractButton; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTabbedPane; import javax.swing.plaf.basic.BasicButtonUI; /** * 可关闭的JTabbedPane标签 * * @author monitor Created on 2011-2-25, 23:52:41 */ public class TabbedPanel extends JPanel { private final JTabbedPane pane; public TabbedPanel(final JTabbedPane pane) { super(new FlowLayout(FlowLayout.LEFT, 0, 0)); if (pane == null) { throw new NullPointerException("TabbedPane is null"); } this.pane = pane; setOpaque(false); //tab标题 JLabel label = new JLabel() { @Override public String getText() { int i = pane.indexOfTabComponent(TabbedPanel.this); if (i != -1) { return pane.getTitleAt(i); } return null; } }; add(label); label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 2)); add(new TabButton()); setBorder(BorderFactory.createEmptyBorder(1, 0, 0, 0)); } /** * tab上的关闭按钮 */ private class TabButton extends JButton { public TabButton() { int size = 17; setPreferredSize(new Dimension(size, size)); setToolTipText("关闭"); setUI(new BasicButtonUI()); setContentAreaFilled(false); setFocusable(false); setBorder(BorderFactory.createEtchedBorder()); setBorderPainted(false); //翻转效果 setRolloverEnabled(true); //鼠标事件,进入时画边框,移出时取消边框 // addMouseListener(new MouseAdapter() { // @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); // } // } // }); //单击关闭按钮事件 addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { int i = pane.indexOfTabComponent(TabbedPanel.this); if (i != -1) { pane.remove(i); } } }); } @Override public void updateUI() { } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g.create(); //鼠标按下时偏移一个坐标点 if (getModel().isPressed()) { g2.translate(1, 1); } g2.setStroke(new BasicStroke(2)); g2.setColor(Color.BLACK); //鼠标在按钮上时为红色 // if (getModel().isRollover()) { // g2.setColor(Color.RED); // } int delta = 6; g2.drawLine(delta, delta, getWidth() - delta - 1, getHeight() - delta - 1); g2.drawLine(getWidth() - delta - 1, delta, delta, getHeight() - delta - 1); g2.dispose(); } } }
ClosableTabbedPane.java
import java.awt.BasicStroke; import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import javax.swing.*; /** * 创建一个可关闭的TabbedPane * @author yz * */ public class ClosableTabbedPane extends JTabbedPane{ private static final long serialVersionUID = 1L; private TabCloseUI closeUI = new TabCloseUI(this); public void paint(Graphics g){ super.paint(g); closeUI.paint(g); } /** * 避免TAB标题和close挤在一起,留2个空格位置 */ public void addTab(String title, Component component) { super.addTab(title+" ", component); } public String getTabTitleAt(int index) { return super.getTitleAt(index).trim(); } private class TabCloseUI implements MouseListener, MouseMotionListener { private ClosableTabbedPane tabbedPane; private int closeX = 0 ,closeY = 0, meX = 0, meY = 0; private int selectedTab; private final int width = 6, height = 6; private Rectangle rectangle = new Rectangle(0,0,width, height); public TabCloseUI(ClosableTabbedPane pane) { tabbedPane = pane; tabbedPane.addMouseMotionListener(this); tabbedPane.addMouseListener(this); } public void mouseEntered(MouseEvent me) {} public void mouseExited(MouseEvent me) {} public void mousePressed(MouseEvent me) {} public void mouseClicked(MouseEvent me) {} public void mouseDragged(MouseEvent me) {} public void mouseReleased(MouseEvent me) { if(closeUnderMouse(me.getX(), me.getY())){ boolean isToCloseTab = tabAboutToClose(selectedTab); if (isToCloseTab && selectedTab > -1){ tabbedPane.removeTabAt(selectedTab); } selectedTab = tabbedPane.getSelectedIndex(); } } public void mouseMoved(MouseEvent me) { meX = me.getX(); meY = me.getY(); if(mouseOverTab(meX, meY)){ controlCursor(); tabbedPane.repaint(); } } private void controlCursor() { if(tabbedPane.getTabCount()>0){ if(closeUnderMouse(meX, meY)){ tabbedPane.setCursor(new Cursor(Cursor.HAND_CURSOR)); if(selectedTab > -1){ tabbedPane.setToolTipTextAt(selectedTab, "Close " +tabbedPane.getTitleAt(selectedTab)); } } else{ tabbedPane.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); if(selectedTab > -1){ tabbedPane.setToolTipTextAt(selectedTab,""); } } } } private boolean closeUnderMouse(int x, int y) { rectangle.x = closeX; rectangle.y = closeY; return rectangle.contains(x,y); } public void paint(Graphics g) { int tabCount = tabbedPane.getTabCount(); for(int j = 0; j < tabCount; j++) if(tabbedPane.getComponent(j).isShowing()){ int x = tabbedPane.getBoundsAt(j).x + tabbedPane.getBoundsAt(j).width -width-5; int y = tabbedPane.getBoundsAt(j).y +5; drawClose(g,x,y); break; } if(mouseOverTab(meX, meY)){ drawClose(g,closeX,closeY); } } private void drawClose(Graphics g, int x, int y) { if(tabbedPane != null && tabbedPane.getTabCount() > 0){ Graphics2D g2 = (Graphics2D)g; //鼠标悬停的时候切换颜色 drawColored(g2, isUnderMouse(x,y)? Color.RED : Color.BLACK, x, y); } } private void drawColored(Graphics2D g2, Color color, int x, int y) { g2.setColor(color); //设置画笔大小2个像素 g2.setStroke(new BasicStroke(2)); g2.drawLine(x, y, x + width, y + height); g2.drawLine(x + width, y, x, y + height); } private boolean isUnderMouse(int x, int y) { return Math.abs(x-meX)<width && Math.abs(y-meY)<height; } private boolean mouseOverTab(int x, int y) { int tabCount = tabbedPane.getTabCount(); for(int j = 0; j < tabCount; j++){ if(tabbedPane.getBoundsAt(j).contains(meX, meY)){ selectedTab = j; closeX = tabbedPane.getBoundsAt(j).x + tabbedPane.getBoundsAt(j).width -width-5; closeY = tabbedPane.getBoundsAt(j).y +5; return true; } } return false; } } public boolean tabAboutToClose(int tabIndex) { return true; } }
ClosableTabbedPane调用也很简单,直接new ClosableTabbedPane就行了。
ClosableTabbedPane tabbedPane = new ClosableTabbedPane() { /** * 关闭提示框,不用可以删掉 */ public boolean tabAboutToClose(int tabIndex) { String tab = tabbedPane.getTabTitleAt(tabIndex); int choice = JOptionPane.showConfirmDialog(null, "You are about to close '" + tab + "'\nDo you want to proceed ?", "Confirmation Dialog", JOptionPane.INFORMATION_MESSAGE); return choice == 0; // if returned false tab closing will be // canceled } };
<strong>ButtonTabComponent.java:</strong>
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package org.javaweb.jrat.server.ui; import javax.swing.*; import javax.swing.plaf.basic.BasicButtonUI; import java.awt.*; import java.awt.event.*; /** * Component to be used as tabComponent; Contains a JLabel to show the text and * a JButton to close the tab it belongs to */ public class ButtonTabComponent extends JPanel { private final JTabbedPane pane; public ButtonTabComponent(final JTabbedPane pane) { //unset default FlowLayout' gaps super(new FlowLayout(FlowLayout.LEFT, 0, 0)); if (pane == null) { throw new NullPointerException("TabbedPane is null"); } this.pane = pane; setOpaque(false); //make JLabel read titles from JTabbedPane JLabel label = new JLabel() { public String getText() { int i = pane.indexOfTabComponent(ButtonTabComponent.this); if (i != -1) { return pane.getTitleAt(i); } return null; } }; add(label); //add more space between the label and the button label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); //tab button JButton button = new TabButton(); add(button); //add more space to the top of the component setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0)); } private class TabButton extends JButton implements ActionListener { public TabButton() { int size = 17; setPreferredSize(new Dimension(size, size)); setToolTipText("close this tab"); //Make the button looks the same for all Laf's setUI(new BasicButtonUI()); //Make it transparent setContentAreaFilled(false); //No need to be focusable setFocusable(false); setBorder(BorderFactory.createEtchedBorder()); setBorderPainted(false); //Making nice rollover effect //we use the same listener for all buttons addMouseListener(buttonMouseListener); setRolloverEnabled(true); //Close the proper tab by clicking the button addActionListener(this); } public void actionPerformed(ActionEvent e) { int i = pane.indexOfTabComponent(ButtonTabComponent.this); if (i != -1) { pane.remove(i); } } //we don't want to update UI for this button public void updateUI() { } //paint the cross protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g.create(); //shift the image for pressed buttons if (getModel().isPressed()) { g2.translate(1, 1); } g2.setStroke(new BasicStroke(2)); g2.setColor(Color.BLACK); if (getModel().isRollover()) { g2.setColor(Color.MAGENTA); } int delta = 6; g2.drawLine(delta, delta, getWidth() - delta - 1, getHeight() - delta - 1); g2.drawLine(getWidth() - delta - 1, delta, delta, getHeight() - delta - 1); g2.dispose(); } } private final static MouseListener buttonMouseListener = new MouseAdapter() { public void mouseEntered(MouseEvent e) { Component component = e.getComponent(); if (component instanceof AbstractButton) { AbstractButton button = (AbstractButton) component; button.setBorderPainted(true); } } public void mouseExited(MouseEvent e) { Component component = e.getComponent(); if (component instanceof AbstractButton) { AbstractButton button = (AbstractButton) component; button.setBorderPainted(false); } } }; }