Java tutorial
import java.awt.AWTEvent; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLayer; import javax.swing.JPanel; import javax.swing.JTabbedPane; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.WindowConstants; import javax.swing.plaf.LayerUI; public class Main { public JComponent makeUI() { UIManager.put("TabbedPane.tabInsets", new Insets(2, 2, 2, 50)); final JTabbedPane tabbedPane = new JTabbedPane(); tabbedPane.addTab("A", new JPanel()); JPanel p = new JPanel(new BorderLayout()); p.add(new JLayer<JTabbedPane>(tabbedPane, new CloseableTabbedPaneLayerUI())); p.add(new JButton(new AbstractAction("add tab") { @Override public void actionPerformed(ActionEvent e) { tabbedPane.addTab("test", new JPanel()); } }), BorderLayout.SOUTH); return p; } public static void main(String[] args) { JFrame f = new JFrame(); f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); f.getContentPane().add(new Main().makeUI()); f.setSize(320, 240); f.setVisible(true); } } class MyCloseButton extends JButton { public MyCloseButton() { super("x"); setBorder(BorderFactory.createEmptyBorder()); setFocusPainted(false); setBorderPainted(false); setContentAreaFilled(false); setRolloverEnabled(false); } @Override public Dimension getPreferredSize() { return new Dimension(16, 16); } }; class CloseableTabbedPaneLayerUI extends LayerUI<JTabbedPane> { JPanel p = new JPanel(); Point pt = new Point(-100, -100); MyCloseButton button = new MyCloseButton(); public CloseableTabbedPaneLayerUI() { super(); } @Override public void paint(Graphics g, JComponent c) { super.paint(g, c); if (c instanceof JLayer == false) { return; } JLayer jlayer = (JLayer) c; JTabbedPane tabPane = (JTabbedPane) jlayer.getView(); for (int i = 0; i < tabPane.getTabCount(); i++) { Rectangle rect = tabPane.getBoundsAt(i); Dimension d = button.getPreferredSize(); int x = rect.x + rect.width - d.width - 2; int y = rect.y + (rect.height - d.height) / 2; Rectangle r = new Rectangle(x, y, d.width, d.height); button.setForeground(r.contains(pt) ? Color.RED : Color.BLACK); SwingUtilities.paintComponent(g, button, p, r); } } @Override public void installUI(JComponent c) { super.installUI(c); ((JLayer) c).setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK); } @Override public void uninstallUI(JComponent c) { ((JLayer) c).setLayerEventMask(0); super.uninstallUI(c); } @Override protected void processMouseEvent(MouseEvent e, JLayer<? extends JTabbedPane> l) { if (e.getID() != MouseEvent.MOUSE_CLICKED) { return; } pt.setLocation(e.getPoint()); JTabbedPane tabbedPane = (JTabbedPane) l.getView(); int index = tabbedPane.indexAtLocation(pt.x, pt.y); if (index >= 0) { Rectangle rect = tabbedPane.getBoundsAt(index); Dimension d = button.getPreferredSize(); int x = rect.x + rect.width - d.width - 2; int y = rect.y + (rect.height - d.height) / 2; Rectangle r = new Rectangle(x, y, d.width, d.height); if (r.contains(pt)) { tabbedPane.removeTabAt(index); } } l.getView().repaint(); } @Override protected void processMouseMotionEvent(MouseEvent e, JLayer<? extends JTabbedPane> l) { pt.setLocation(e.getPoint()); JTabbedPane tabbedPane = (JTabbedPane) l.getView(); int index = tabbedPane.indexAtLocation(pt.x, pt.y); if (index >= 0) { tabbedPane.repaint(tabbedPane.getBoundsAt(index)); } else { tabbedPane.repaint(); } } }