JTabbedPane自定义组件布局

时间:2016-07-10 09:44:21

标签: java swing jtabbedpane

我正在看这个例子Using Swing Components; Examples。此示例显示JTabbedPane带有自定义标签组件,每个标签中都有关闭按钮。

如果JTabbedPane位于WRAP_TAB_LAYOUT标签标题中,则关闭按钮位于宽标签的中间。如何更改此选项卡选项卡中心仍然可以看到选项卡标题,但关闭按钮会出现在右侧选项卡边框旁边?

这是一张图片:

enter image description here

1 个答案:

答案 0 :(得分:1)

  • 以下是使用UIManager.put("TabbedPane.tabInsets", insets)JLayer的一种可能实施方式
    • 使用JLayer
    • 在选项卡的内边缘绘制关闭按钮
    • 我没有在NumbusLookAndFeel
    • 上进行测试

enter image description here

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.plaf.*;

public class RightCloseTabButtonTest {
  public JComponent makeUI() {
    JTabbedPane tabs = new JTabbedPane();
    tabs.addTab("Tab 1", new JLabel("aaa"));
    tabs.addTab("Tab 2", new JLabel("bbb"));
    tabs.addTab("Tab 3", new JLabel("ccc"));
    tabs.addTab("Tab 4", new JLabel("ddd"));
    return new JLayer<JTabbedPane>(tabs, new CloseableTabbedPaneLayerUI());
  }
  public static void main(String... args) {
    EventQueue.invokeLater(() -> {
      UIManager.put("TabbedPane.tabInsets", new Insets(2, 2 + 16, 2, 2 + 16));
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new RightCloseTabButtonTest().makeUI());
      f.setSize(300, 240);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}

class CloseTabIcon implements Icon {
  @Override public void paintIcon(Component c, Graphics g, int x, int y) {
    Graphics2D g2 = (Graphics2D) g.create();
    g2.translate(x, y);
    g2.setPaint(Color.BLACK);
    if (c instanceof AbstractButton) {
      ButtonModel m = ((AbstractButton) c).getModel();
      if (m.isRollover()) {
        g2.setPaint(Color.ORANGE);
      }
    }
    g2.drawLine(4,  4, 11, 11);
    g2.drawLine(4,  5, 10, 11);
    g2.drawLine(5,  4, 11, 10);
    g2.drawLine(11, 4,  4, 11);
    g2.drawLine(11, 5,  5, 11);
    g2.drawLine(10, 4,  4, 10);
    g2.dispose();
  }
  @Override public int getIconWidth() {
    return 16;
  }
  @Override public int getIconHeight() {
    return 16;
  }
}

class CloseableTabbedPaneLayerUI extends LayerUI<JTabbedPane> {
  private final JComponent rubberStamp = new JPanel();
  private final Point pt = new Point();
  private final JButton button = new JButton(new CloseTabIcon()) {
    @Override public void updateUI() {
      super.updateUI();
      setBorder(BorderFactory.createEmptyBorder());
      setFocusPainted(false);
      setBorderPainted(false);
      setContentAreaFilled(false);
      setRolloverEnabled(false);
    }
  };
  @Override public void paint(Graphics g, JComponent c) {
    super.paint(g, c);
    if (c instanceof JLayer) {
      JLayer jlayer = (JLayer) c;
      JTabbedPane tabPane = (JTabbedPane) jlayer.getView();
      Dimension d = button.getPreferredSize();
      for (int i = 0; i < tabPane.getTabCount(); i++) {
        Rectangle rect = tabPane.getBoundsAt(i);
        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.getModel().setRollover(r.contains(pt));
        SwingUtilities.paintComponent(g, button, rubberStamp, r);
      }
    }
  }
  @Override public void installUI(JComponent c) {
    super.installUI(c);
    if (c instanceof JLayer) {
      ((JLayer) c).setLayerEventMask(
          AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
    }
  }
  @Override public void uninstallUI(JComponent c) {
    if (c instanceof JLayer) {
      ((JLayer) c).setLayerEventMask(0);
    }
    super.uninstallUI(c);
  }
  @Override protected void processMouseEvent(
      MouseEvent e, JLayer<? extends JTabbedPane> l) {
    if (e.getID() == MouseEvent.MOUSE_CLICKED) {
      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);
        }
      }
    }
  }
  @Override protected void processMouseMotionEvent(
      MouseEvent e, JLayer<? extends JTabbedPane> l) {
    pt.setLocation(e.getPoint());
    JTabbedPane t = (JTabbedPane) l.getView();
    if (t.indexAtLocation(pt.x, pt.y) >= 0) {
      Point loc = e.getPoint();
      loc.translate(-16, -16);
      l.repaint(new Rectangle(loc, new Dimension(32, 32)));
    }
  }
}