Swing/FileAndTextTransferHandler のバックアップの現在との差分(No.1)
- category: swing folder: FileAndTextTransferHandler title: JTextComponentにファイルとテキストをドロップ可能に設定する tags: [JTextComponent, DragAndDrop, DropTargetListener, TransferHandler] author: aterai pubdate: 2022-11-21T00:21:27+09:00 description: JTextComponentにデフォルトの文字列だけでなくファイルもドロップ可能になるよう設定します。 description: JTextComponentにデフォルトの文字列だけでなくファイルもドロップ可能になるようなTransferHandlerを設定します。 image: https://drive.google.com/uc?id=19UPpYiiOmU-vIAHpCt35QmXdofVKz3nO
概要
JTextComponentにデフォルトの文字列だけでなくファイルもドロップ可能になるよう設定します。JTextComponent
にデフォルトの文字列だけでなくファイルもドロップ可能になるようなTransferHandler
を設定します。
Screenshot
Advertisement
サンプルコード
public void addTab(File file) {
JTextArea textArea = new JTextArea();
textArea.setDragEnabled(true);
new DropTarget(textArea, DnDConstants.ACTION_COPY, new FileDropTargetListener(), true);
new DropTarget(textArea, DnDConstants.ACTION_COPY,
new FileDropTargetListener(), true);
if (file != null) {
try (Reader in = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)) {
try (Reader in = Files.newBufferedReader(
file.toPath(), StandardCharsets.UTF_8)) {
textArea.read(in, "File");
tabbedPane.addTab(file.getName(), new JScrollPane(textArea));
} catch (IOException ex) {
UIManager.getLookAndFeel().provideErrorFeedback(textArea);
}
} else {
tabbedPane.addTab("*untitled*", new JScrollPane(textArea));
}
tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
}
#spandel
public void addFile(Transferable transferable) throws UnsupportedFlavorException, IOException {
#spanend
List<?> list = (List<?>) transferable.getTransferData(DataFlavor.javaFileListFlavor);
#spanadd
public void addFile(Transferable transferable)
#spanend
throws UnsupportedFlavorException, IOException {
List<?> list = (List<?>) transferable.getTransferData(
DataFlavor.javaFileListFlavor);
new SwingWorker<Void, Void>() {
@Override protected Void doInBackground() {
for (Object o : list) {
if (o instanceof File) {
addTab((File) o);
}
}
return null;
}
}.execute();
}
private class FileDropTargetListener extends DropTargetAdapter {
@Override public void drop(DropTargetDropEvent e) {
Transferable transferable = e.getTransferable();
if (e.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
e.acceptDrop(DnDConstants.ACTION_COPY);
try {
addFile(transferable);
e.dropComplete(true);
} catch (UnsupportedFlavorException | IOException ex) {
e.dropComplete(false);
}
} else {
JTextComponent textArea = (JTextComponent) e.getSource();
TransferHandler textHandler = textArea.getTransferHandler();
if (textHandler != null) {
textHandler.importData(textArea, transferable);
}
}
}
}
private class FileTransferHandler extends TransferHandler {
@Override public boolean canImport(TransferSupport support) {
// System.out.println(support.getComponent().getClass().getName());
boolean isDrop = support.isDrop();
boolean supported = support.isDataFlavorSupported(DataFlavor.javaFileListFlavor);
boolean supported = support.isDataFlavorSupported(
DataFlavor.javaFileListFlavor);
return supported && isDrop;
}
@Override public boolean importData(TransferSupport support) {
// System.out.println(support.getComponent().getClass().getName());
Transferable transferable = support.getTransferable();
try {
addFile(transferable);
return true;
} catch (IOException | UnsupportedFlavorException ex) {
return false;
}
}
}
View in GitHub: Java, Kotlin解説
FileTransferHandler
を設定したJFrame
- 子コンポーネントやタイトルバーを含む領域にファイルをドロップ可能
Window window = SwingUtilities.getWindowAncestor(tabbedPane); if (window instanceof JFrame) { ((JFrame) window).setTransferHandler(new FileTransferHandler()); }
- 子コンポーネントやタイトルバーを含む領域にファイルをドロップ可能
- デフォルトの
JTextArea
-
BasicTextUI.TextTransferHandler
がデフォルトで設定されているのでテキスト文字列を別コンポーネントなどがドロップ可能だが、JFrame
に設定したFileTransferHandler
は打ち消されるためファイルのドロップは不可 -
BasicTextUI.TextTransferHandler
がデフォルトで設定されているのでテキスト文字列を別コンポーネントなどからドロップ(ペースト)可能だが、親JFrame
に設定したFileTransferHandler
はこのBasicTextUI.TextTransferHandler
に打ち消されるためファイルのドロップは不可 JTextArea#setDragEnabled(true)
を設定して選択文字列をドラッグ可能に設定
-
FileDropTargetListener
を追加したJTextArea
DropTargetAdapter#drop(...)
をオーバーライドしてドロップイベントがDataFlavor.javaFileListFlavor
をサポートしている場合はファイルをJTextArea
に読み込んでJTabbedPane
に追加、それ以外はJTextArea
からBasicTextUI.TextTransferHandler
を取得してTransferHandler#importData(...)
を実行してテキストをドロップJTextArea#setDragEnabled(true)
を設定すれば選択文字列をドラッグ可能になるが、テキストドラッグオーバー中のキャレット描画に未対応
JTextArea
にJFrame
に設定したFileTransferHandler
を設定すると、デフォルトのBasicTextUI.TextTransferHandler
が置き換えられてテキストがドロップ不可になる- これを回避するため、以下のような
TransferHandler
でラップしてファイルとテキストのドロップに対応する方法もあるが、JTextArea#setDragEnabled(true)
を設定済みのJTextArea
でも文字列を選択してドラッグアウトが不可になる
TransferHandler textHandler = textArea.getTransferHandler();
TransferHandler fileHandler = new FileTransferHandler();
textArea.setTransferHandler(new TransferHandler() {
@Override public boolean canImport(TransferSupport support) {
return fileHandler.canImport(support) || textHandler.canImport(support);
}
@Override public boolean importData(TransferSupport support) {
if (support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
return fileHandler.importData(support);
} else {
return textHandler.importData(support);
}
}
});