繁体   English   中英

Java Swing - ActionListener比KeyListener慢得多

[英]Java Swing - ActionListener much slower than KeyListener

对于一个程序,当按下按钮“1”时,我正在使用KeyListener向ArrayList添加内容。 此列表中的对象不断可视化。 使用KeyListener,即使按下按钮,这也能流畅地工作。

后来,我在GUI中添加了一个JMenuBar。 向ArrayList添加内容现在有一个自己的JMenuItem,其加速器设置为KeyStroke'1',ActionListener执行与之前的KeyListener相同的东西。 但是,现在的表现非常糟糕。 按下'1'将会非常滞后,与KeyListener相比,速度非常慢。

为什么这么慢? 难道我做错了什么? 有没有更好的办法?

    ...
    AL al = new AL();
    menu.add(createMenuItem("Add", KeyEvent.VK_1, al));
}

private JMenuItem createMenuItem(String text, int key, ActionListener al){
    JMenuItem menuItem = new JMenuItem(text);
    menuItem.setAccelerator(KeyStroke.getKeyStroke(key, 0));
    menuItem.addActionListener(al);
    return menuItem;
}

private class AL implements ActionListener{
    public void actionPerformed(ActionEvent e){
        int keycode = ((JMenuItem)e.getSource()).getAccelerator().getKeyCode();
        bla(keycode);
    }
}

看起来减速是菜单加速器的处理方式。 它可能是L&F甚至操作系统,因为当我对它进行分析时,Java代码(WindowsXP)中没有热点。 解决方法可能是将键绑定添加到根窗格而不是使用菜单加速器。

按'1'按钮触发KeyListener(快速)按'2'触发菜单加速器(慢)按'3'按钮触发按键(快速)按'4'按钮触发根窗格上的快速键(快速)

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;

public class TestKeySpeed {
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                final JTextArea area = new JTextArea(20, 40);
                area.setEditable(false);

                JButton button = new JButton("Just something that has focus");
                button.addKeyListener(new KeyAdapter() {
                    @Override
                    public void keyPressed(KeyEvent e) {
                        if (e.getKeyCode() == KeyEvent.VK_1) {
                            area.append("1");
                        }
                    }
                });

                AbstractAction action = new AbstractAction("Add") {
                    {
                        putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke('2'));
                    }

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        area.append("2");
                    }
                };
                button.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
                        KeyStroke.getKeyStroke('3'), "add3");
                button.getActionMap().put("add3", action);

                JMenu menu = new JMenu("File");
                menu.add(action);
                JMenuBar bar = new JMenuBar();
                bar.add(menu);
                JFrame frame = new JFrame("Test");
                frame.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
                        KeyStroke.getKeyStroke('4'), "add4");
                frame.getRootPane().getActionMap().put("add4", action);

                frame.setJMenuBar(bar);
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                frame.getContentPane().add(new JScrollPane(area));
                frame.getContentPane().add(button, BorderLayout.PAGE_END);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                button.requestFocusInWindow();
            }
        });
    }
}

其他东西正在减慢您的应用程序。 示例仍然响应十几个键绑定 一种有用的方法是让菜单项和其他组件共享相同的操作 ,如此此处所示。

附录:不是实现ActionListener ,而是通过扩展AbstractAction实现Action ,这将使管理加速键更容易。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM