Swing/DnDLayerTabbedPane のバックアップの現在との差分(No.7)
- バックアップ一覧
- 差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- バックアップ を表示
- Swing/DnDLayerTabbedPane へ行く。
- 1 (2012-01-23 (月) 18:01:31)
- 2 (2012-01-23 (月) 19:26:33)
- 3 (2012-01-25 (水) 19:57:10)
- 4 (2012-12-13 (木) 15:47:56)
- 5 (2013-07-26 (金) 01:10:28)
- 6 (2014-09-15 (月) 15:08:08)
- 7 (2014-10-19 (日) 19:01:01)
- 8 (2014-11-27 (木) 17:53:18)
- 9 (2015-03-31 (火) 21:04:47)
- 10 (2016-05-22 (日) 21:17:19)
- 11 (2017-08-15 (火) 14:46:08)
- 12 (2018-02-24 (土) 19:51:30)
- 13 (2018-08-15 (水) 20:31:16)
- 14 (2018-11-01 (木) 21:41:36)
- 15 (2019-05-22 (水) 19:35:38)
- 16 (2020-10-31 (土) 00:24:08)
- 17 (2022-09-14 (水) 05:25:32)
- 追加された行はこの色です。
- 削除された行はこの色です。
--- category: swing folder: DnDLayerTabbedPane title: JLayerを使ってJTabbedPaneのタブの挿入位置を描画する tags: [JLayer, JTabbedPane, DragAndDrop, TransferHandler, JWindow, JLabel] author: aterai pubdate: 2012-01-23T18:01:31+09:00 description: JLayerを使って、タブのドラッグ&ドロップでの移動先をJTabbedPane上に描画します。 image: https://lh3.googleusercontent.com/-xX0rzgauC5c/Txz4AxE_u2I/AAAAAAAABIM/jHQdxU1yP9g/s800/DnDLayerTabbedPane.png hreflang: href: https://java-swing-tips.blogspot.com/2012/01/sharing-tabs-between-2-jframes.html lang: en --- * 概要 [#t75e37f6] * 概要 [#summary] `JLayer`を使って、タブのドラッグ&ドロップでの移動先を`JTabbedPane`上に描画します。 #download(https://lh3.googleusercontent.com/-xX0rzgauC5c/Txz4AxE_u2I/AAAAAAAABIM/jHQdxU1yP9g/s800/DnDLayerTabbedPane.png) * サンプルコード [#d057781e] * サンプルコード [#sourcecode] #code(link){{ class DropLocationLayerUI extends LayerUI<DnDTabbedPane> { private static final int LINEWIDTH = 3; private final Rectangle lineRect = new Rectangle(); @Override public void paint(Graphics g, JComponent c) { super.paint (g, c); JLayer layer = (JLayer)c; DnDTabbedPane tabbedPane = (DnDTabbedPane)layer.getView(); DnDTabbedPane.DropLocation loc = tabbedPane.getDropLocation(); if(loc != null && loc.isDropable() && loc.getIndex()>=0) { int index = loc.getIndex(); boolean isZero = index==0; Rectangle r = tabbedPane.getBoundsAt(isZero?0:index-1); if(tabbedPane.getTabPlacement()==JTabbedPane.TOP || tabbedPane.getTabPlacement()==JTabbedPane.BOTTOM) { lineRect.setRect( r.x-LINEWIDTH/2+r.width*(isZero?0:1), r.y,LINEWIDTH,r.height); }else{ lineRect.setRect( r.x,r.y-LINEWIDTH/2+r.height*(isZero?0:1), r.width,LINEWIDTH); super.paint(g, c); if (c instanceof JLayer) { JLayer layer = (JLayer) c; DnDTabbedPane tabbedPane = (DnDTabbedPane) layer.getView(); DnDTabbedPane.DropLocation loc = tabbedPane.getDropLocation(); if (loc != null && loc.isDroppable() && loc.getIndex() >= 0) { Graphics2D g2 = (Graphics2D) g.create(); g2.setComposite( AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .5f)); g2.setColor(Color.RED); initLineRect(tabbedPane, loc); g2.fill(lineRect); g2.dispose(); } Graphics2D g2 = (Graphics2D)g.create(); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f)); g2.setColor(Color.RED); g2.fill(lineRect); g2.dispose(); } } private void initLineRect(JTabbedPane tabbedPane, DnDTabbedPane.DropLocation loc) { int index = loc.getIndex(); int a = index == 0 ? 0 : 1; Rectangle r = tabbedPane.getBoundsAt(a * (index - 1)); if (tabbedPane.getTabPlacement() == JTabbedPane.TOP || tabbedPane.getTabPlacement() == JTabbedPane.BOTTOM) { lineRect.setBounds( r.x - LINE_WIDTH / 2 + r.width * a, r.y, LINE_WIDTH, r.height); } else { lineRect.setBounds( r.x, r.y - LINE_WIDTH / 2 + r.height * a, r.width, LINE_WIDTH); } } } }} * 解説 [#se007f95] 上記のサンプルでは、[[JTabbedPaneのタブをドラッグ&ドロップ>Swing/DnDTabbedPane]]や、[[JTabbedPane間でタブのドラッグ&ドロップ移動>Swing/DnDExportTabbedPane]]のように`GlassPane`を使用する代わりに、`JDK 1.7.0`で導入された`JLayer`を使用して、タブの挿入先を描画しています。`JLayer`を使用することで、別ウィンドウにある`JTabbedPane`へのタブ移動などの描画が簡単にできるようになっています。 * 解説 [#explanation] 上記のサンプルでは、[[JTabbedPaneのタブをドラッグ&ドロップ>Swing/DnDTabbedPane]]や、[[JTabbedPane間でタブのドラッグ&ドロップ移動>Swing/DnDExportTabbedPane]]のように`GlassPane`を使用する代わりに、`JDK 1.7.0`で導入された`JLayer`を使用してタブの挿入先を描画しています。`JLayer`を使用することで別ウィンドウにある`JTabbedPane`へのタブ移動などの描画が簡単になります。 ---- メニューバーから、ドラッグ中の半透明タブイメージの描画方法を切り替えてテストすることができます。 メニューバーからドラッグ中の半透明タブイメージの描画方法を切り替えてテストできます。 - `Lightweight` -- `JDK1.7.0`で導入された、`TransferHandler#setDragImage(...)`メソッドを使用して描画 -- ウィンドウの外では非表示 -- ウィンドウの外部では非表示 - `Heavyweight` -- 半透明の`JWindow`に`JLabel`を追加して表示 -- ウィンドウの外でも表示可能 -- ウィンドウの外部でも表示可能 -- 表示位置のオフセットが`(0, 0)`の場合、`DragOver`イベントが元の`JFrame`に伝わらない? --- オフセットが`(0, 0)`でも、`JLabel#contains(...)`が常に`false`なら問題なし #code{{ private final JLabel label = new JLabel() { @Override public boolean contains(int x, int y) { return false; } }; private final JWindow dialog = new JWindow(); public TabTransferHandler() { dialog.add(label); //dialog.setAlwaysOnTop(true); // Web Start dialog.setOpacity(0.5f); //com.sun.awt.AWTUtilities.setWindowOpacity(dialog, 0.5f); // JDK 1.6.0 // dialog.setAlwaysOnTop(true); // Web Start dialog.setOpacity(.5f); // com.sun.awt.AWTUtilities.setWindowOpacity(dialog, .5f); // JDK 1.6.0 DragSource.getDefaultDragSource().addDragSourceMotionListener( new DragSourceMotionListener() { @Override public void dragMouseMoved(DragSourceDragEvent dsde) { Point pt = dsde.getLocation(); pt.translate(5, 5); // offset dialog.setLocation(pt); } }); //... // ... }} * 参考リンク [#t09438dd] * 参考リンク [#reference] - [[JTabbedPaneのタブをドラッグ&ドロップ>Swing/DnDTabbedPane]] - [[JTabbedPane間でタブのドラッグ&ドロップ移動>Swing/DnDExportTabbedPane]] - [http://free-the-pixel.blogspot.com/2010/04/ghost-drag-and-drop-over-multiple.html Free the pixel: GHOST drag and drop, over multiple windows] * コメント [#b93fe731] * コメント [#comment] #comment - `JFrame`の外にドロップした場合は、新しいフレームと`JTabbedPane`を作成して表示したいけど、KBD{Esc}キーや右クリックでのキャンセルと区別がつかない?ので、難しそう。 -- &user(aterai); &new{2012-01-25 (水) 19:57:10}; #comment