Swing/DnDExportTabbedPane のバックアップ(No.10)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - 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間でタブのドラッグ&ドロップ移動
Posted by terai at 2009-03-23
JTabbedPane間でタブのドラッグ&ドロップ移動
JTabbedPane間でタブのDrag&Dropによる移動を行います。
- &jnlp;
- &jar;
- &zip;
#screenshot
サンプルコード
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());
}
@Override public boolean canImport(TransferHandler.TransferSupport support) {
//System.out.println("canImport");
if (!support.isDrop() || !support.isDataFlavorSupported(localObjectFlavor)) {
return false;
}
support.setDropAction(TransferHandler.MOVE);
TransferHandler.DropLocation tdl = support.getDropLocation();
Point pt = tdl.getDropPoint();
DnDTabbedPane target = (DnDTabbedPane)support.getComponent();
target.autoScrollTest(pt);
DnDTabbedPane.DropLocation dl =
(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;
} else {
//System.out.println("target!=source");
isDropable = 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) {
support.setShowDropLocation(true);
dl.setDropable(true);
target.setDropLocation(dl, null, true);
return true;
} else {
support.setShowDropLocation(false);
dl.setDropable(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);
BufferedImage image = new BufferedImage(
c.getWidth(), c.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics g = image.getGraphics();
c.paint(g);
if (rect.x<0) {
rect.translate(-rect.x,0);
}
if (rect.y<0) {
rect.translate(0,-rect.y);
}
if (rect.x+rect.width>image.getWidth()) {
rect.width = image.getWidth() - rect.x;
}
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;
}
@Override public boolean importData(TransferHandler.TransferSupport support) {
System.out.println("importData");
if (!canImport(support)) return false;
DnDTabbedPane target = (DnDTabbedPane)support.getComponent();
DnDTabbedPane.DropLocation dl = target.getDropLocation();
try {
DnDTabbedPane source =
(DnDTabbedPane)support.getTransferable().getTransferData(localObjectFlavor);
int index = dl.getIndex(); //boolean insert = dl.isInsert();
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) {
ioe.printStackTrace();
}
return false;
}
@Override protected void exportDone(JComponent c, Transferable data, int action) {
System.out.println("exportDone");
DnDTabbedPane src = (DnDTabbedPane)c;
c.getRootPane().getGlassPane().setVisible(false);
src.setDropLocation(null, null, false);
}
private GhostGlassPane glassPane;
}
解説
上記のサンプルでは、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)
参考リンク
コメント
- タブのドラッグ中、JTable上などでCursorが点滅するのを修正。 -- terai
- 点滅の原因は? -- Dad?
- おそらく、Cursor flickering during D&D when using CellRendererPane with validationが原因。現在は、canImport メソッド内で、一々GlassPane#setCursor(isDropable?DragSource.DefaultMoveDrop:DragSource.DefaultMoveNoDrop);として回避中。 -- terai
- 6u20ぐらいからWebStartで、java.security.AccessControlException: access denied (java.awt.AWTPermission accessClipboard)? -- terai