Вероятно, существует некоторое недопонимание того, как работает передача.
Попытка извлечения данных переноса непосредственно в виде строки может работать для «текста / обычного» или других стандартных типов текста и, как вы заметили, с некоторыми причудами для конкретных случаев нестандартного незарегистрированного типа.Но я не думаю, что усилия для пользовательских обходных путей оправданы.
Поскольку вы полностью контролируете структуру содержимого для пользовательского типа MIME, а также оба конца источника данных и потребителя в одном приложении, я предлагаю неиметь дело с внутренними префиксами, зависящими от реализации инструментария, или отображениями классов.Вероятно, лучше просто определить свой тип MIME без несвязанных метаданных и искаженных префиксов (как это и должно быть).
Определение типа «application / x-my-mime » и правильноедолжно быть достаточно декодирования данных.
Пример 1 (сериализованные данные)
Нижеприведенное исправление из вашего примера должно сбрасывать данные в фрейм Swing в Java 8.
package jfxtest;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.datatransfer.DataFlavor;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.Collections;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.input.DataFormat;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.BorderPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.TransferHandler;
import javax.swing.TransferHandler.TransferSupport;
public class MyApp {
final static String MY_MIME_TYPE = "application/x-my-mime";
public static final DataFormat FORMAT = new DataFormat(MY_MIME_TYPE);
public static final DataFlavor FLAVOR = new DataFlavor(MY_MIME_TYPE, "My Mime Type");
private void startDrag(Node node) {
node.startDragAndDrop(TransferMode.COPY).setContent(
Collections.singletonMap(FORMAT, "Test"));
}
private boolean processData(TransferSupport support) {
try (InputStream in = (InputStream) support.getTransferable().getTransferData(FLAVOR)) {
Object transferred = new ObjectInputStream(in).readObject();
System.out.println("transferred: " + transferred + " (" + transferred.getClass() + ")");
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public static void main(String[] args) {
new MyApp().run();
}
private void run() {
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(1, 2));
frame.add(buildSwing());
SwingUtilities.invokeLater(() -> {
frame.add(buildFX());
});
frame.setSize(300, 300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private JFXPanel buildFX() {
BorderPane parent = new BorderPane();
parent.setOnDragDetected(event -> {
startDrag(parent);
event.consume();
});
JFXPanel panel = new JFXPanel();
panel.setScene(new Scene(parent));
return panel;
}
private JPanel buildSwing() {
JPanel panel = new JPanel();
panel.setBackground(Color.ORANGE);
panel.setTransferHandler(new TransferHandler() {
private static final long serialVersionUID = 1L;
@Override
public boolean canImport(TransferSupport support) {
return support.isDataFlavorSupported(FLAVOR);
}
@Override
public boolean importData(TransferSupport support) {
if (canImport(support)) {
return processData(support);
}
return false;
}
});
return panel;
}
}
Вывод: transferred: Test (class java.lang.String)
Здесь приведен существенный отрывок:
...
final static String MY_MIME_TYPE = "application/x-my-mime";
public static final DataFormat FORMAT = new DataFormat(MY_MIME_TYPE);
public static final DataFlavor FLAVOR = new DataFlavor(MY_MIME_TYPE, "My Mime Type");
private void startDrag(Node node) {
node.startDragAndDrop(TransferMode.COPY).setContent(
Collections.singletonMap(FORMAT, "Test"));
}
private boolean processData(TransferSupport support) {
try (InputStream in = (InputStream) support.getTransferable().getTransferData(FLAVOR)) {
Object transferred = new ObjectInputStream(in).readObject();
System.out.println("transferred: " + transferred + " (" + transferred.getClass() + ")");
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
...
Обратите внимание, что поиск данных упрощен в целях иллюстрации, для реального применения.вероятно, хотелось бы добавить более точное чтение потока, обработку ошибок и т. д.
Пример 2 (пользовательский MIME с текстом)
Первый пример передает сериализованный объект (который обычнохорошая и простая вещь, поскольку вы можете передавать все, что можно сериализовать, но затрудняет передачу / прием, скажем, стороннего JSON).В маловероятном случае, когда вы хотите создать реальный текст или другой произвольный контент для пользовательского MIME вместо сериализованного объекта, ниже следует выполнить работу:
package jfxtest;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.datatransfer.DataFlavor;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.input.DataFormat;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.BorderPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.TransferHandler;
import javax.swing.TransferHandler.TransferSupport;
public class MyApp {
final static String MY_MIME_TYPE = "application/x-my-mime";
public static final DataFormat FORMAT = new DataFormat(MY_MIME_TYPE);
public static final DataFlavor FLAVOR = new DataFlavor(MY_MIME_TYPE, "My Mime Type");
private void startDrag(Node node) {
node.startDragAndDrop(TransferMode.COPY).setContent(
// put a ByteBuffer to transfer the content unaffected
Collections.singletonMap(FORMAT, StandardCharsets.UTF_8.encode("Test")));
}
private boolean processData(TransferSupport support) {
try (InputStream in = (InputStream) support.getTransferable().getTransferData(FLAVOR)) {
byte[] textBytes = new byte[in.available()];
in.read(textBytes);
String transferred = new String(textBytes, StandardCharsets.UTF_8);
System.out.println("transferred text: " + transferred);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public static void main(String[] args) {
new MyApp().run();
}
private void run() {
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(1, 2));
frame.add(buildSwing());
SwingUtilities.invokeLater(() -> {
frame.add(buildFX());
});
frame.setSize(300, 300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private JFXPanel buildFX() {
BorderPane parent = new BorderPane();
parent.setOnDragDetected(event -> {
startDrag(parent);
event.consume();
});
JFXPanel panel = new JFXPanel();
panel.setScene(new Scene(parent));
return panel;
}
private JPanel buildSwing() {
JPanel panel = new JPanel();
panel.setBackground(Color.ORANGE);
panel.setTransferHandler(new TransferHandler() {
private static final long serialVersionUID = 1L;
@Override
public boolean canImport(TransferSupport support) {
return support.isDataFlavorSupported(FLAVOR);
}
@Override
public boolean importData(TransferSupport support) {
if (canImport(support)) {
return processData(support);
}
return false;
}
});
return panel;
}
}
Вывод: transferred text: Test
Здесь важная часть:
...
private void startDrag(Node node) {
node.startDragAndDrop(TransferMode.COPY).setContent(
// put a ByteBuffer to transfer the content unaffected
Collections.singletonMap(FORMAT, StandardCharsets.UTF_8.encode("Test")));
}
private boolean processData(TransferSupport support) {
try (InputStream in = (InputStream) support.getTransferable().getTransferData(FLAVOR)) {
byte[] textBytes = new byte[in.available()];
in.read(textBytes);
String transferred = new String(textBytes, StandardCharsets.UTF_8);
System.out.println("transferred text: " + transferred);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
...
Еще раз, в качестве иллюстрации, обработка потока, ошибок и т. Д. Здесь упрощена.
Одна вещь, на которую следует обратить внимание:что существует также предопределенный «application / x-java-serialized-object» (DataFlavor.javaSerializedObjectMimeType
) для более общей и простой десериализации.Но долгосрочный пользовательский MIME кажется более гибким и простым в обращении.