Swing/DockAndUndockTabs のバックアップ(No.2)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/DockAndUndockTabs へ行く。
- 1 (2024-06-03 (月) 01:56:34)
- 2 (2024-06-03 (月) 11:30:23)
- category: swing folder: DockAndUndockTabs title: JTabbedPaneのタブのドラッグアウトで新規JFrameの作成と空JFrameの破棄を実行する tags: [JTabbedPane, TransferHandler, DragAndDrop, JFrame] author: aterai pubdate: 2024-06-03T01:53:27+09:00 description: JTabbedPaneのタブをJFrame外にドラッグアウトした場合はそのタブを含む新規JFrameを作成し、ドラッグ元のJTabbedPaneが空になる場合はその親JFrameごと破棄を実行します。 image: https://drive.google.com/uc?id=16s-3Bs9AtEpgEPhbzapN4qIiwyGjH3K4
概要
JTabbedPane
のタブをJFrame
外にドラッグアウトした場合はそのタブを含む新規JFrame
を作成し、ドラッグ元のJTabbedPane
が空になる場合はその親JFrame
ごと破棄を実行します。
Screenshot
Advertisement
サンプルコード
protected TabTransferHandler() {
super();
dialog.add(label);
dialog.setOpacity(.5f);
DragSource.getDefaultDragSource().addDragSourceMotionListener(e -> {
Point pt = e.getLocation();
pt.translate(5, 5); // offset
dialog.setLocation(pt);
source.pointOnScreen.setLocation(pt);
});
}
@Override protected void exportDone(
JComponent c, Transferable data, int action) {
DnDTabbedPane src = (DnDTabbedPane) c;
if (src.pointOnScreen.x > 0) {
createNewFrame(src);
}
src.updateTabDropLocation(null, false);
src.repaint();
if (src.getTabCount() == 0) {
Optional.ofNullable(SwingUtilities.getWindowAncestor(src))
.ifPresent(Window::dispose);
}
if (mode == DragImageMode.HEAVYWEIGHT && dialog != null) {
dialog.dispose();
}
}
private static void createNewFrame(DnDTabbedPane src) {
int index = src.dragTabIndex;
final Component cmp = src.getComponentAt(index);
// final Component tab = src.getTabComponentAt(index);
final String title = src.getTitleAt(index);
final Icon icon = src.getIconAt(index);
final String tip = src.getToolTipTextAt(index);
src.remove(index);
DnDTabbedPane tabs = new DnDTabbedPane();
tabs.setTransferHandler(src.getTransferHandler());
tabs.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
tabs.addTab(title, icon, cmp, tip);
// tabs.setTabComponentAt(0, tab);
tabs.setTabComponentAt(0, new ButtonTabComponent(tabs));
DropTargetListener listener = new TabDropTargetAdapter();
try {
tabs.getDropTarget().addDropTargetListener(listener);
} catch (TooManyListenersException ex) {
ex.printStackTrace();
UIManager.getLookAndFeel().provideErrorFeedback(tabs);
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.getContentPane().add(
new JLayer<>(tabs, new DropLocationLayerUI()));
frame.setSize(320, 240);
frame.setLocation(src.pointOnScreen);
frame.setVisible(true);
EventQueue.invokeLater(frame::toFront);
}
View in GitHub: Java, Kotlin解説
JFrame
外へのタブドラッグアウトで新規JFrame
作成とJFrame
間でのタブ移動- JTabbedPaneのタブがフレーム外にドロップされたら新規JFrameを作成すると同様に、タブドロップで空ファイルリストを
JFrame
外にコピーすることで新規JFrame
とJTabbedPane
を生成し、タブの移動を実行 - JLayerを使ってJTabbedPaneのタブの挿入位置を描画すると同様に、
TransferHandler
を使用して異なるJFrame
に配置されたJTabbedPane
間でのタブ移動を実行しているため、JTabbedPaneのタブがフレーム外にドロップされたら新規JFrameを作成するのようにDragSourceListener#dragDropEnd(DragSourceDropEvent e)
でドロップ終了時の位置をチェックするのではなくDragSource.getDefaultDragSource().addDragSourceMotionListener(e-> ...)
でドラッグ中の画面でのカーソル位置を記録してTransferHandler#exportDone(...)
実行時に新規JFrame
を作成するかや、その座標に利用している
- JTabbedPaneのタブがフレーム外にドロップされたら新規JFrameを作成すると同様に、タブドロップで空ファイルリストを
- 空
JFrame
の破棄TransferHandler#exportDone(...)
実行時、ドラッグ元のJTabbedPane
のタブ数が0
になるかどうかをチェックして親JFrame
とJTabbedPane
の破棄を実行- JLayerを使ってJTabbedPaneのタブの挿入位置を描画するなどとは異なり、ドラッグ元の
JTabbedPane
のタブ数が1
でもドラッグ可能に変更している