私は、removeAll()
、add()
、revalidate()
のドロップを処理している間に、ドロップが成功し、変更が有効になることに気付きましたが、2度目のドラッグを開始することはできません。それ以降のドラッグの試行ではjava.awt.dnd.InvalidDnDOperationException: Drag and drop in progress
が投げられます。Swingドロップコールバック中に、コンポーネント階層の変更が禁止されていますか?
階層に変更を加えてもドラッグはクリアされないと思われ、スイングは進行中のドラッグがまだ完了していないと考えています。これは、階層の変更は問題はドラッグがまだ完了していないときにコンポーネント階層の変更が発生することがありDropTargetDropEvent.acceptDrop()
とDropTargetDropEvent.dropComplete()
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.dnd.*;
import javax.activation.*;
import java.awt.datatransfer.*;
import java.util.TooManyListenersException;
class MyWidget extends JComponent {
MyWidget() {
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
updateState();
}
void updateState() {
Runnable runnable = new Runnable() {
@Override
public void run() {
// System.out.println("Hello World on " + Thread.currentThread());
removeAll();
add(newButton("aaa"));
add(newButton("bbb"));
revalidate();
}
};
if (SwingUtilities.isEventDispatchThread()) {
runnable.run();
} else {
SwingUtilities.invokeLater(runnable);
}
}
JButton newButton(String text) {
JButton theButton = new JButton(text);
DragSource ds = new DragSource();
DragGestureRecognizer dgr = ds.createDefaultDragGestureRecognizer(theButton, DnDConstants.ACTION_COPY, new DragGestureListener() {
@Override
public void dragGestureRecognized(DragGestureEvent dge) {
Transferable transferable = new DataHandler("my text", "text/plain");
dge.startDrag(DragSource.DefaultCopyDrop, transferable);
}
});
DropTarget dt = new DropTarget();
dt.setComponent(theButton);
try {
dt.addDropTargetListener(new DropTargetAdapter() {
@Override
public void drop(DropTargetDropEvent dtde) {
System.out.println("drop accepted");
dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
dtde.dropComplete(true);
updateState();
}
});
} catch (TooManyListenersException e) {}
return theButton;
}
}
public class App
{
static void createGUI() {
JFrame frame = new JFrame();
frame.setTitle("my app");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new MyWidget(), BorderLayout.CENTER);
frame.setSize(500,500);
// frame.pack();
frame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
System.out.println("Hello World on " + Thread.currentThread());
createGUI();
}
});
}
}