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);
}
}
};
}