我正在尝试对
jtabbedpane
实现拖放行为。
它在我的 Windows 10 上运行良好,但在 Debian 12 上运行不佳(Debian 上的 openjdk 17)。
这是一个最小的测试用例:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.InvalidDnDOperationException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
public class DnDTestCase extends JFrame {
JTabbedPane tabbedPane;
public DnDTestCase() {
tabbedPane = new JTabbedPane(JTabbedPane.TOP);
getContentPane().add(tabbedPane, BorderLayout.CENTER);
JPanel panel = new JPanel();
tabbedPane.addTab("New tab", null, panel, null);
this.setSize(320, 240);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initDnd();
}
void initDnd() {
final DragSourceListener dsl = new DragSourceListener() {
@Override
public void dragEnter(DragSourceDragEvent e) {}
@Override
public void dragExit(DragSourceEvent e) {}
@Override
public void dragOver(DragSourceDragEvent e) {}
@Override
public void dragDropEnd(DragSourceDropEvent e) {
System.out.println("dragDropEnd()");
}
@Override
public void dropActionChanged(DragSourceDragEvent e) {}
};
final DragGestureListener dgl = new DragGestureListener() {
@Override
public void dragGestureRecognized(DragGestureEvent e) {
System.out.println("dragGestureRecognized()");
try {
e.startDrag(DragSource.DefaultMoveDrop,
new Transferable() {
@Override
public Object getTransferData(DataFlavor flavor) {
return null;
}
@Override
public DataFlavor[] getTransferDataFlavors() {
return null;
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return true;
}
},
dsl);
} catch (InvalidDnDOperationException idoe) {
idoe.printStackTrace();
}
}
};
DragSource ds = new DragSource();
ds.createDefaultDragGestureRecognizer(tabbedPane, DnDConstants.ACTION_MOVE, dgl);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new DnDTestCase().setVisible(true));
}
}
这里是
Windows
。[JFrame+JtabPane]
基本上,您可以将选项卡拖放到窗口本身,也可以拖放到
JFrame
之外的空白区域,在这两种情况下,在 Windows 上,释放鼠标按钮时都会触发 dragDropEnd
功能。所以它在终端中显示 dragDropEnd()
。这很好。
但是,在
Linux
运行中,仅当鼠标光标位于 dragDropEnd
上方时才会触发 JFrame
(显然,原始的一个或什至另一个,这并不重要)。
如果在空白处释放鼠标按钮(=不是
JFrame
— 甚至可能是 JDialog
),它不会触发任何操作,直到鼠标光标移回到 JFrame
上。因此,由于某种原因,如果鼠标不在 JFrame
上,则不会生成事件?
我是否明显做错了什么?