首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Java回调速度

Java回调速度
EN

Stack Overflow用户
提问于 2011-12-17 17:16:47
回答 1查看 3.3K关注 0票数 2

关于regarding中的mouseDragged消息的回调速度,我有一个问题。这个职位是相关的,但并不完全相同,所以我提出了一个自己的问题。

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

我的图形用户界面由一个带有菜单的JFrame和一些包含各种按钮和标签的面板组成,但是我只会查看相关的部分来解释我的问题。

本质上,我使用的是一个垂直拆分的JSplitPane,左边有一个JPanel,其中有一个带有JListJScrollPane,它在任何时候都代表着你手上的牌,你可以玩。在拆分的右侧,我有一个JLayeredPane,它在DEFAULT_LAYER (重写draw函数以添加图像的JPanel子类)中有一个背景图像,并且在PALETTE_LAYER之上的各个层上,我通过自定义CardPanels (说明卡片的另一个JPanel子类)显示正在使用的卡片(聚集在ArrayList中)。因此,整个JLayeredPane是你面前的桌子的一个表示法,你已经打过所有的牌了。

我首先将一个MouseListener和一个MouseMotionListener添加到JLayeredPane中以获取事件,允许我注册鼠标按下,检查这是否在卡片上,然后使用鼠标拖动事件来移动卡片,最后用鼠标释放将其放回。这一切都很好,如果我添加日志记录信息,我可以看到mouseDragged回调函数经常被调用,这样就可以在没有滞后的情况下进行可视化的快速拖动。

今天,我决定添加一些功能,允许用户将一张卡片从手中拖到“表”(而不是双击JList中的卡片),因此我向JList添加了适当的侦听器,并填充了一些函数,比如MousePressedMouseReleased。在鼠标按下时,我检查从列表中单击了什么卡,锁定了列表,创建了一个自定义的CardPanel (但是现在还没有添加它,我只是分配和启动它!)并设置一面旗子。在鼠标拖动中,我检查是否设置了此标志。如果是,我检查光标在哪里。如果它高于JLayeredPane,则将CardPanel添加到DRAG_LAYER并设置另一个标志。如果在连续调用鼠标拖动时设置了第二个标志,我不会再添加面板,而是更改位置。此功能实际上与上一次鼠标拖动回调中的功能相同。在鼠标发布时,我解锁列表并将CardPanel添加到JLayeredPane的正确层。

所有工作都按预期进行,所以我确信我的代码没有问题,但有一个小问题:

当将卡片从列表拖到分层窗格(而不是从分层窗格拖到分层窗格)时,我注意到mouseDragged回调是由JList以相当低的频率调用的(大约每秒10次),引入了一些视觉上令人不安的滞后(在第一个拖放的情况下是每秒大约30次)。

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

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

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

代码语言:javascript
运行
复制
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);
                    }
            }
        }
        });
    }

我将尝试构建一个简短的可运行示例,再现问题,然后将代码附加到某个地方,但现在我开始使用skoot。

提前感谢

PS:我知道在Java中还有另一种拖放方式,涉及TransferHandlers和所有这些,但这似乎太麻烦了,而且这并不是对我的问题的实际回答,为什么一个回调似乎比另一个调用更多,所以请不要告诉我要使用它。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-01-17 13:01:02

一旦拖动到列表之外,Java就开始为列表生成合成鼠标事件,这可能是原因之一。请参阅JComponent#setAutoscrolls的javadoc (布尔值)。

使用全局事件侦听器可以获得更好的结果,请参见http://tips4java.wordpress.com/2009/08/30/global-event-listeners/

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8546487

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档