Swing/CloseableTabbedPane の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/CloseableTabbedPane へ行く。
- Swing/CloseableTabbedPane の差分を削除
--- category: swing folder: CloseableTabbedPane title: JTabbedPaneの各タブにJButtonを右寄せで追加する tags: [JTabbedPane, JButton, JLayer] author: aterai pubdate: 2014-07-21T03:51:17+09:00 description: JTabbedPaneのタブ上にそれを閉じるためのJButtonをJLayerを使用して右寄せで描画します。 image: https://lh4.googleusercontent.com/-slZiu9Gyq8I/U8wH6A1byMI/AAAAAAAACJ0/-aLfrJeKX4Y/s800/CloseableTabbedPane.png --- * 概要 [#summary] `JTabbedPane`のタブ上にそれを閉じるための`JButton`を`JLayer`を使用して右寄せで描画します。 #download(https://lh4.googleusercontent.com/-slZiu9Gyq8I/U8wH6A1byMI/AAAAAAAACJ0/-aLfrJeKX4Y/s800/CloseableTabbedPane.png) * サンプルコード [#sourcecode] #code(link){{ class CloseableTabbedPaneLayerUI extends LayerUI<JTabbedPane> { private final JComponent rubberStamp = new JPanel(); private final Point pt = new Point(-100, -100); private final JButton button = new JButton(new CloseTabIcon()); public CloseableTabbedPaneLayerUI() { super(); button.setBorder(BorderFactory.createEmptyBorder()); button.setFocusPainted(false); button.setBorderPainted(false); button.setContentAreaFilled(false); button.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(); 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.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 tabbedPane = (JTabbedPane) l.getView(); int index = tabbedPane.indexAtLocation(pt.x, pt.y); if (index >= 0) { Point loc = e.getPoint(); loc.translate(-16, -16); l.repaint(new Rectangle(loc, new Dimension(32, 32))); } } } }} * 解説 [#explanation] - 上 -- [[JTabbedPaneにタブを閉じるボタンを追加>Swing/TabWithCloseButton]] -- タブに追加したコンポーネントは、中央揃えで配置される -- タブに追加したコンポーネントは中央揃えで配置される --- `BasicTabbedPaneUI`などのデフォルト - 下 -- `JLayer`を使用して、タブの余白にそれを閉じるための`JButton`を描画 -- `JLayer`を使用してタブの余白にそれを閉じるための`JButton`を描画 --- `TabbedPaneUI`をオーバーライドする必要がない --- [[JTabbedPaneにタブを閉じるアイコンを追加>Swing/TabWithCloseIcon]]では、`BasicTabbedPaneUI#createLayoutManager()`をオーバーライドして、独自の`TabbedPaneLayout`で右端に☓アイコンを描画 -- タブの余白は`UIManager.put("TabbedPane.tabInsets", new Insets(2, 18, 2, 18));`で設定 --- この余白設定は、`NimbusLookAndFeel`などでは無効 --- 左右の余白の合計よりタブが短くなる場合、ボタンがタイトルに重なってしまう * 参考リンク [#reference] - [https://stackoverflow.com/questions/24634047/closeable-jtabbedpane-alignment-of-the-close-button java - Closeable JTabbedPane - alignment of the close button - Stack Overflow] - [[JTabbedPaneにタブを閉じるボタンを追加>Swing/TabWithCloseButton]] - [[JTabbedPaneにタブを閉じるアイコンを追加>Swing/TabWithCloseIcon]] * コメント [#comment] #comment #comment