Swing/DnDExportTabbedPane のバックアップの現在との差分(No.11)
- バックアップ一覧
- 差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- バックアップ を表示
- Swing/DnDExportTabbedPane へ行く。
- 1 (2009-03-23 (月) 14:24:48)
- 2 (2009-03-23 (月) 15:42:01)
- 3 (2009-05-19 (火) 17:31:12)
- 4 (2010-01-16 (土) 01:48:13)
- 5 (2010-01-16 (土) 12:25:38)
- 6 (2010-02-23 (火) 18:00:10)
- 7 (2010-06-17 (木) 01:57:34)
- 8 (2010-06-17 (木) 14:31:14)
- 9 (2010-06-17 (木) 15:44:07)
- 10 (2010-06-18 (金) 19:05:42)
- 11 (2010-07-08 (木) 21:54:27)
- 12 (2010-07-22 (木) 18:40:09)
- 13 (2010-07-23 (金) 14:35:15)
- 14 (2010-09-29 (水) 16:35:44)
- 15 (2010-09-30 (木) 16:16:35)
- 16 (2010-12-20 (月) 22:02:00)
- 17 (2012-02-05 (日) 11:13:40)
- 18 (2012-02-10 (金) 16:36:54)
- 19 (2013-01-10 (木) 17:54:46)
- 20 (2013-09-15 (日) 00:20:42)
- 21 (2014-11-01 (土) 00:46:09)
- 22 (2014-12-02 (火) 01:45:48)
- 23 (2015-01-23 (金) 19:25:52)
- 24 (2015-12-15 (火) 17:04:56)
- 25 (2016-05-26 (木) 14:44:43)
- 26 (2016-06-01 (水) 18:48:21)
- 27 (2017-03-29 (水) 15:44:09)
- 28 (2017-04-04 (火) 14:17:08)
- 29 (2017-08-15 (火) 14:45:52)
- 30 (2017-11-02 (木) 15:34:40)
- 31 (2017-11-17 (金) 19:54:09)
- 32 (2018-02-24 (土) 19:51:30)
- 33 (2019-07-17 (水) 14:58:33)
- 34 (2019-10-23 (水) 21:27:36)
- 35 (2021-05-27 (木) 16:28:46)
- 36 (2022-08-20 (土) 22:15:25)
- 追加された行はこの色です。
- 削除された行はこの色です。
TITLE:JTabbedPane間でタブのドラッグ&ドロップ移動 #navi(../) RIGHT:Posted by [[terai]] at 2009-03-23 *JTabbedPane間でタブのドラッグ&ドロップ移動 [#yae9971e] JTabbedPane間でタブのDrag&Dropによる移動を行います。 --- category: swing folder: DnDExportTabbedPane title: JTabbedPane間でタブのドラッグ&ドロップ移動 tags: [JTabbedPane, TransferHandler, DragAndDrop, GlassPane, Cursor] author: aterai pubdate: 2009-03-23T14:24:48+09:00 description: JTabbedPane間でタブのDrag&Dropによる移動を行います。 image: https://lh5.googleusercontent.com/_9Z4BYR88imo/TQTLW06ZMXI/AAAAAAAAAXc/vzeXm4pwhVY/s800/DnDExportTabbedPane.png hreflang: href: https://java-swing-tips.blogspot.com/2010/02/tabtransferhandler.html lang: en --- * 概要 [#summary] `JTabbedPane`間でタブの`Drag&Drop`による移動を行います。 -&jnlp; -&jar; -&zip; #download(https://lh5.googleusercontent.com/_9Z4BYR88imo/TQTLW06ZMXI/AAAAAAAAAXc/vzeXm4pwhVY/s800/DnDExportTabbedPane.png) #screenshot * サンプルコード [#sourcecode] #code(link){{ class TabTransferHandler extends TransferHandler { private final DataFlavor localObjectFlavor = new DataFlavor(DnDTabData.class, "DnDTabData"); private DnDTabbedPane source = null; **サンプルコード [#e06345a4] #code{{ class TabTransferHandler extends TransferHandler { private final DataFlavor localObjectFlavor; public TabTransferHandler() { System.out.println("TabTransferHandler"); localObjectFlavor = new ActivationDataFlavor( DnDTabbedPane.class, DataFlavor.javaJVMLocalObjectMimeType, "DnDTabbedPane"); } @Override protected Transferable createTransferable(JComponent c) { System.out.println("createTransferable"); return new DataHandler(c, localObjectFlavor.getMimeType()); if (c instanceof DnDTabbedPane) source = (DnDTabbedPane) c; return new Transferable() { @Override public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[] {localObjectFlavor}; } @Override public boolean isDataFlavorSupported(DataFlavor flavor) { return Objects.equals(localObjectFlavor, flavor); } @Override public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { if (isDataFlavorSupported(flavor)) { return new DnDTabData(source); } else { throw new UnsupportedFlavorException(flavor); } } }; } @Override public boolean canImport(TransferHandler.TransferSupport support) { //System.out.println("canImport"); @Override public boolean canImport(TransferSupport support) { // System.out.println("canImport"); if (!support.isDrop() || !support.isDataFlavorSupported(localObjectFlavor)) { return false; } support.setDropAction(TransferHandler.MOVE); TransferHandler.DropLocation tdl = support.getDropLocation(); DropLocation tdl = support.getDropLocation(); Point pt = tdl.getDropPoint(); DnDTabbedPane target = (DnDTabbedPane)support.getComponent(); DnDTabbedPane target = (DnDTabbedPane) support.getComponent(); target.autoScrollTest(pt); DnDTabbedPane.DropLocation dl = (DnDTabbedPane.DropLocation)target.dropLocationForPoint(pt); (DnDTabbedPane.DropLocation) target.dropLocationForPoint(pt); int idx = dl.getIndex(); boolean isDropable = false; if (target==source) { //System.out.println("target==source"); isDropable = target.getTabAreaBounds().contains(pt) && idx>=0 && idx!=target.dragTabIndex && idx!=target.dragTabIndex+1; boolean isDroppable = false; if (target == source) { isDroppable = target.getTabAreaBounds().contains(pt) && idx >= 0 && idx != target.dragTabIndex && idx != target.dragTabIndex + 1; } else { //System.out.println("target!=source"); isDropable = target.getTabAreaBounds().contains(pt) && idx>=0; if (source != null && target != source.getComponentAt(source.dragTabIndex)) { isDroppable = target.getTabAreaBounds().contains(pt) && idx >= 0; } } Component c = target.getRootPane().getGlassPane(); if (c instanceof GhostGlassPane) { GhostGlassPane gp = (GhostGlassPane)c; gp.setCursor(isDropable?DragSource.DefaultMoveDrop:DragSource.DefaultMoveNoDrop); } if (isDropable) { c.setCursor(isDroppable?DragSource.DefaultMoveDrop:DragSource.DefaultMoveNoDrop); if (isDroppable) { support.setShowDropLocation(true); dl.setDropable(true); dl.setDroppable(true); target.setDropLocation(dl, null, true); return true; } else { support.setShowDropLocation(false); dl.setDropable(false); dl.setDroppable(false); target.setDropLocation(dl, null, false); return false; } } private DnDTabbedPane source = null; @Override public int getSourceActions(JComponent c) { System.out.println("getSourceActions"); source = (DnDTabbedPane)c; if (glassPane==null) glassPane = new GhostGlassPane(source); Rectangle rect = source.getBoundsAt(source.dragTabIndex); private BufferedImage makeDragTabImage(DnDTabbedPane tabbedPane) { Rectangle rect = tabbedPane.getBoundsAt(tabbedPane.dragTabIndex); BufferedImage image = new BufferedImage( c.getWidth(), c.getHeight(), BufferedImage.TYPE_INT_ARGB); tabbedPane.getWidth(), tabbedPane.getHeight(), BufferedImage.TYPE_INT_ARGB); Graphics g = image.getGraphics(); c.paint(g); if (rect.x<0) { rect.translate(-rect.x,0); tabbedPane.paint(g); g.dispose(); if (rect.x < 0) { rect.translate(-rect.x, 0); } if (rect.y<0) { rect.translate(0,-rect.y); if (rect.y < 0) { rect.translate(0, -rect.y); } if (rect.x+rect.width>image.getWidth()) { if (rect.x + rect.width > image.getWidth()) { rect.width = image.getWidth() - rect.x; } if (rect.y+rect.height>image.getHeight()) { if (rect.y + rect.height > image.getHeight()) { rect.height = image.getHeight() - rect.y; } BufferedImage img = image.getSubimage(rect.x,rect.y,rect.width,rect.height); glassPane.setImage(img); //setDragImage(img); //java 1.7.0-ea-b84 c.getRootPane().setGlassPane(glassPane); glassPane.setVisible(true); return TransferHandler.MOVE; return image.getSubimage(rect.x, rect.y, rect.width, rect.height); } @Override public boolean importData(TransferHandler.TransferSupport support) { @Override public int getSourceActions(JComponent c) { System.out.println("getSourceActions"); if (c instanceof DnDTabbedPane) { DnDTabbedPane src = (DnDTabbedPane) c; c.getRootPane().setGlassPane(new GhostGlassPane(src)); if (src.dragTabIndex < 0) { return TransferHandler.NONE; } setDragImage(makeDragTabImage(src)); c.getRootPane().getGlassPane().setVisible(true); return TransferHandler.MOVE; } return TransferHandler.NONE; } @Override public boolean importData(TransferSupport support) { System.out.println("importData"); if (!canImport(support)) return false; DnDTabbedPane target = (DnDTabbedPane)support.getComponent(); DnDTabbedPane target = (DnDTabbedPane) support.getComponent(); DnDTabbedPane.DropLocation dl = target.getDropLocation(); try { DnDTabbedPane source = (DnDTabbedPane)support.getTransferable().getTransferData(localObjectFlavor); DnDTabbedPane source = (DnDTabbedPane) support.getTransferable() .getTransferData(localObjectFlavor); int index = dl.getIndex(); //boolean insert = dl.isInsert(); if (target==source) { if (target == source) { source.convertTab(source.dragTabIndex, index); } else { source.exportTab(source.dragTabIndex, target, index); } return true; } catch (UnsupportedFlavorException ufe) { ufe.printStackTrace(); } catch (java.io.IOException ioe) { } catch (IOException ioe) { ioe.printStackTrace(); } return false; } @Override protected void exportDone(JComponent c, Transferable data, int action) { System.out.println("exportDone"); DnDTabbedPane src = (DnDTabbedPane)c; DnDTabbedPane src = (DnDTabbedPane) c; c.getRootPane().getGlassPane().setVisible(false); src.setDropLocation(null, null, false); } private GhostGlassPane glassPane; } }} **解説 [#o96b9e3f] 上記のサンプルでは、JDK 6 で導入された、TransferHandler.DropLocationを継承するDnDTabbedPane.DropLocationなどを作成して、JTabbedPane間でタブの移動ができるように設定しています。 * 解説 [#explanation] 上記のサンプルでは、`JDK 6`で導入された、`TransferHandler.DropLocation`を継承する`DnDTabbedPane.DropLocation`などを作成して、`JTabbedPane`間でタブの移動ができるように設定しています。 -注意点 --自身の子であるJTabbedPaneにタブを移動することはできない --子コンポーネントがnull(例えばaddTab("Tab",null))のタブは移動不可 --タブが選択不可(例えばsetEnabledAt(idx, false))の場合は移動不可 -バグ? --%%子コンポーネントがJTableの場合、マウスカーソルが点滅する%% ---%%Windows環境のみ?%% --子コンポーネントがJTextAreaなどの場合、ドラッグ中のタブゴーストが表示できない ---%%JTable、JTextAreaどちらも、JScrollPaneが影響している?%% ---java 1.7.0-ea-b84 で、TransferHandler#setDragImage(Image) を使用するとちゃんと表示される --SCROLL_TAB_LAYOUTの場合、タブゴーストにスクロールボタンが表示される場合がある > #screenshot(,screenshot1.png) - 注意点 -- 自身の子として配置されている`JTabbedPane`にタブを移動することはできない -- 子コンポーネントが`null`(例えば`addTab("Tab",null)`)のタブは移動不可 -- タブが選択不可(例えば`setEnabledAt(idx, false)`)の場合は移動不可 - バグ? -- %%子コンポーネントが`JTable`の場合、マウスカーソルが点滅する%% --- %%`Windows`環境のみ?%% -- 子コンポーネントが`JTextArea`などの場合、ドラッグ中のタブゴーストが表示できない --- %%`JTable`、`JTextArea`どちらも`JScrollPane`が影響している?%% ---`Java 1.7.0-ea-b84`以上で、`TransferHandler#setDragImage(Image)`を使用すると正常に表示される --- `textArea.setTransferHandler(null);`とすれば、`1.6.0`でも正常に表示される -- `SCROLL_TAB_LAYOUT`の場合、タブゴーストにスクロールボタンが表示される場合がある **参考リンク [#y58f4e18] -[[JTabbedPaneのタブをドラッグ&ドロップ>Swing/DnDTabbedPane]] #ref(https://lh6.googleusercontent.com/_9Z4BYR88imo/TQTLZe_UIkI/AAAAAAAAAXg/bCzrlm037N8/s800/DnDExportTabbedPane1.png) **コメント [#gcad5394] - タブのドラッグ中、JTable上などでCursorが点滅するのを修正。 -- [[terai]] &new{2009-05-19 (火) 17:32:38}; - 点滅の原因は? -- [[Dad]] &new{2010-01-16 (土) 01:48:13}; -- おそらく、[[Cursor flickering during D&D when using CellRendererPane with validation>http://bugs.sun.com/view_bug.do?bug_id=6700748]]が原因。現在は、canImport メソッド内で、一々GlassPane#setCursor(isDropable?DragSource.DefaultMoveDrop:DragSource.DefaultMoveNoDrop);として回避中。 -- [[terai]] &new{2010-01-16 (土) 12:25:38}; - 6u20ぐらいからWebStartで、java.security.AccessControlException: access denied (java.awt.AWTPermission accessClipboard)? -- [[terai]] &new{2010-06-17 (木) 01:57:34}; -- チュートリアルのデモ[[Demo - DropDemo (The Java™ Tutorials > Creating a GUI With JFC/Swing Drag and Drop and Data Transfer)>http://java.sun.com/docs/books/tutorial/uiswing/dnd/dropmodedemo.html]]でも同様のエラーが発生するので多分Java 1.6.0_??のバグ。 -- [[terai]] &new{2010-06-17 (木) 14:31:14}; -- 6u21では、修正されている?: [[6945178 2-High Defect SecurityException upon drag-and-drop(Bug/RFE fixed in JDK 6u21 build)>http://download.java.net/jdk6/6u21/promoted/b05/changes/JDK6u21.b05.list.html]] -- [[terai]] &new{2010-06-17 (木) 14:32:45}; * 参考リンク [#reference] - [[JTabbedPaneのタブをドラッグ&ドロップ>Swing/DnDTabbedPane]] - [[JLayerを使ってJTabbedPaneのタブの挿入位置を描画する>Swing/DnDLayerTabbedPane]] * コメント [#comment] #comment - タブのドラッグ中、`JTable`上などで`Cursor`が点滅するのを修正。 -- &user(aterai); &new{2009-05-19 (火) 17:32:38}; - 点滅の原因は? -- &user(Dad); &new{2010-01-16 (土) 01:48:13}; -- おそらく、[https://bugs.openjdk.org/browse/JDK-6700748 Cursor flickering during D&D when using CellRendererPane with validation]が原因。現在は、`canImport`メソッド内で、一々`GlassPane#setCursor(isDroppable ? DragSource.DefaultMoveDrop : DragSource.DefaultMoveNoDrop);`として回避中。 -- &user(aterai); &new{2010-01-16 (土) 12:25:38}; - `6u20`ぐらいから`Web Start`で、`java.security.AccessControlException: access denied (java.awt.AWTPermission accessClipboard)`? -- &user(aterai); &new{2010-06-17 (木) 01:57:34}; -- チュートリアルのデモ[https://docs.oracle.com/javase/tutorial/uiswing/dnd/dropmodedemo.html Demo - DropDemo (The Java™ Tutorials > Creating a GUI With JFC/Swing Drag and Drop and Data Transfer)]でも同様のエラーが発生するので多分`Java 1.6.0_??`のバグ。 -- &user(aterai); &new{2010-06-17 (木) 14:31:14}; -- `6u21`では、修正されている?: [http://download.java.net/jdk6/6u21/promoted/b05/changes/JDK6u21.b05.list.html 6945178 2-High Defect SecurityException upon drag-and-drop(Bug/RFE fixed in JDK 6u21 build)] -- &user(aterai); &new{2010-06-17 (木) 14:32:45}; -- 修正されたようです。[http://www.oracle.com/technetwork/java/javase/bugfixes6u21-156339.html Java SE 6 Update 21 Bug Fixes] -- &user(aterai); &new{2010-07-08 (木) 21:54:27}; - `getTabPlacement()==RIGHT`などの場合に、`DropTarget`の描画がおかしくなるのを修正。 -- &user(aterai); &new{2012-02-05 (日) 11:13:40}; #comment