Java Swing鼠标标记回调速度

Java Swing鼠标标记回调速度,java,swing,mouse,drag,Java,Swing,Mouse,Drag,我有一个关于Java Swing中MouseMotionListener的mouseDragged消息的回调速度的问题。有点相关,但不完全一样,所以我开始问自己的问题 我正在制作一个小型的内部应用程序,它基本上是一个数字化的TCG(交易卡游戏)模拟器,不关注商业发行。对于任何熟悉MtG(魔法聚会)的人来说,你可能都听过类似的节目。我正试图创造一些看起来有点像但不那么花哨的东西 我的GUI由一个带有菜单的JFrame和一些包含各种按钮和标签的面板组成,但我将只讨论相关部分来解释我的问题 本质上,我

我有一个关于Java Swing中
MouseMotionListener
mouseDragged
消息的回调速度的问题。有点相关,但不完全一样,所以我开始问自己的问题

我正在制作一个小型的内部应用程序,它基本上是一个数字化的TCG(交易卡游戏)模拟器,不关注商业发行。对于任何熟悉MtG(魔法聚会)的人来说,你可能都听过类似的节目。我正试图创造一些看起来有点像但不那么花哨的东西

我的GUI由一个带有菜单的JFrame和一些包含各种按钮和标签的面板组成,但我将只讨论相关部分来解释我的问题

本质上,我使用的是一个垂直拆分的
JSplitPane
,左边是一个
JPanel
,里面是一个
JScrollPane
,里面有一个
JList
,它随时代表你手上可以玩的牌。在拆分的右侧,我有一个
JLayeredPane
,在
DEFAULT_层
中有一个背景图像(覆盖
draw
功能以添加图像的
JPanel的子类),并且在
调色板_层
上方的各个层上,我显示正在使用的牌(收集在
ArrayList
中)通过自定义
CardPanel
s(另一个子类
JPanel
演示一张牌)。因此,整个
JLayeredPane
代表了您面前的桌子以及您已经玩过的所有牌

首先,我在
JLayeredPane
中添加了一个
MouseListener
和一个
MouseMotionListener
来拾取事件,允许我注册一次鼠标按下,检查这是否在卡片上方,然后使用鼠标拖动事件来移动卡片,最后释放鼠标将其放回原位。这一切都非常有效如果我添加日志信息,我可以看到经常调用
mouseDragged
回调函数,允许视觉上快速拖动运动而不延迟

今天,我决定添加功能,允许用户将一张卡从手中拖到“表”中(而不是双击
JList
中的卡),因此我在
JList
中添加了相应的侦听器,并填充了一些函数,如
MousePressed
mouseerelease
。按下鼠标,我会检查列表中单击的卡,锁定列表,创建自定义
CardPanel
(但现在还没有添加它,我只是分配并启动它!)并设置一个标志。在鼠标拖动中,我检查是否设置了该标志。如果设置了,我检查光标的位置。如果光标位于
JLayeredPane
上方的任何位置,我将
CardPanel
添加到
DRAG\u层
,并设置另一个标志。如果在连续调用鼠标拖动时设置了第二个标志,我不会再次添加该面板,但我只添加了c更改位置。此功能实际上与上次鼠标拖动回调中的功能相同。释放鼠标时,我解锁列表并将
CardPanel
添加到
JLayeredPane
的正确层上

一切都按预期进行,所以我很确定我的代码是正确的,但只有一个小问题:

当将卡片从列表拖动到分层窗格(而不是从分层窗格拖动到分层窗格)时,我注意到
mouseDragged
回调被
JList
以相当低的频率调用(大约每秒10次),引入了一些视觉上令人不安的延迟(相比之下,第一次拖动约为每秒30次)

为了澄清我的问题,我将添加一些代码片段,但我担心添加所有代码以允许您自己运行它将是严重的过度使用

这篇文章的主要问题是:有人知道为什么一个
MouseMotionListener
调用
mouseDragged
比另一个
MouseMotionListener
调用得更快吗?
JLayeredPane
组件的侦听器进行快速连续调用,而
JList
的侦听器调用速度明显较慢

注意:我正在使用Netbeans开发,我正在使用内置的图形Swing界面生成器。我正在使用JFrame表单作为我的主类

public class MyFrame extends JFrame{
    ...
    protected JLayeredPane layeredPane;
    protected JList cardsInHandList;
    ...

    ...
    protected ArrayList<String> cardsInHand;
    ...

    private void attachListeners(){
        layeredPane.addMouseListener(new MouseAdapter(){
            public void MousePressed(MouseEvent e){
                // set a flag, start a drag
            }
            public void MouseReleased(MouseEvent e){
                // unset a flag, stop a drag
            }
        });
        layeredPane.addMouseMotionListener(new MouseMotionAdapter(){
            public void MouseDragged(MouseEvent e){
                // drag the card around
                // gets called a lot!

                // actual code:
                if (e.getButton() == MouseEvent.BUTTON1) {
                if (!dragging) return; // the flag

                int x = e.getX() - 10;
                int y = e.getY() - 10;

                // snap to grid
                x /= GRIDX;
                x *= GRIDX;

                y /= GRIDY;
                y *= GRIDY;

                // redraw the card at its new location
                draggedCard.setLocation(x, y);
            }
            }
        });

        cardsInHandList.addMouseListener(new MouseAdapter(){
            public void MousePressed(MouseEvent e){
                // set a flag, start a drag
            }
            public void MouseReleased(MouseEvent e){
                // unset a flag, stop a drag
            }
        });
        cardsInHandList.addMouseMotionListener(new MouseMotionAdapter(){
            public void MouseDragged(MouseEvent evt){
                // check cursor location, drag if within bounds of layeredPane
                // gets called a whole lot less!! _Why?_

                // actual code:
            if (!draggingFromHand) return; // the flag

            // check location of cursor with own method (contains() didn't work for me)
            if (isCursorAtPointAboveLayeredPane(evt.getLocationOnScreen())) {

                // calculate where and snap to grid
                int x = (int) (evt.getLocationOnScreen().getX() - layeredPane.getLocationOnScreen().getX())-10;
                int y = (int) (evt.getLocationOnScreen().getY() - layeredPane.getLocationOnScreen().getY())-10;

                    // snap to grid
                x /= GRIDX;
                x *= GRIDX;
                y /= GRIDY;
                y *= GRIDY;

                    if(!draggingFromHandCardPanelAdded){
                        layeredPane.add(draggingFromHandCardPanel, JLayeredPane.DRAG_LAYER);
                        draggingFromHandCardPanelAdded = true;
                    } else {
                    draggingFromHandCardPanel.setLocation(x,y);
                    }
            }
        }
        });
    }
公共类MyFrame扩展了JFrame{
...
受保护的JLayeredPane layeredPane;
受保护的JList cardsInHandList;
...
...
受保护的ArrayList cardsInHand;
...
私有void附件侦听器(){
layeredPane.addMouseListener(新的MouseAdapter(){
公共无效鼠标按下(MouseEvent e){
//设置标志,开始拖动
}
公共无效MouseEvent(MouseEvent e){
//取消设置标志,停止拖动
}
});
layeredPane.addMouseMotionListener(新的MouseMotionAdapter(){
公共无效鼠标标记(鼠标事件e){
//把卡片拖来拖去
//经常被叫来!
//实际代码:
如果(例如getButton()==MouseEvent.BUTTON1){
if(!drawing)return;//标志
int x=e.getX()-10;
int y=e.getY()-10;
//捕捉到网格
x/=GRIDX;
x*=GRIDX;
y/=GRIDY;
y*=网格;
//在新位置重新绘制卡片
draggedCard.设置位置(x,y);
}
}
});
cardsInHandList.addMouseListener(新的MouseAdapter(){
公共无效鼠标按下(MouseEvent e){
//设置标志,开始拖动
}
公共无效MouseEvent(MouseEvent e){
//取消设置标志,停止拖动
}
});
cardsInHandList.addMouseMotionListener(新的MouseMotionAd