【问题标题】:Java enter key the same as submit button?Java输入键与提交按钮相同吗?
【发布时间】:2020-03-31 22:20:32
【问题描述】:

程序应该做的是用回车键模仿“旋转”按钮。该程序可以运行并且不会崩溃,但 Eclipse 控制台在线程“AWT-EventQueue-0”中给了我一个“异常”java.lang.ClassCastException:javax.swing.JTextField 无法转换为 javax。 swing.JButton" 错误。

//.. gui code
        spin = new JButton("Spin");
        bet = new JTextField("");

        play p = new play();
        spin.addActionListener(p);
        keys k = new keys();
        bet.addKeyListener(k);  
}

private class play implements ActionListener{
    public void actionPerformed(ActionEvent e) {
        JButton src = (JButton) e.getSource();
        if(src.equals(spin)) {
            //do something
        }
}

private class keys implements KeyListener{
    @Override
    public void keyTyped(KeyEvent e) {
        char c= e.getKeyChar();
        if(c == KeyEvent.VK_ENTER) {
            spin.doClick();
        }
    }
//.. the other override methods
}

编辑

  • 还有 2 个按钮,我只是没有包含它们,因为它们工作正常且功能不同。
  • JTextField 有一个 KeyListener,因为我从字母中过滤掉了数字,所以我会使用该事件。不能让用户用字母下注吧?

【问题讨论】:

  • JTextFields 也可以有 ActionListeners。当您在文本字段中按下回车键时,将调用这些动作侦听器。因此,您可以在文本字段和按钮上添加相同的 ActionListener,而无需检查源是什么。即使有,也不需要将 is 转换为 JButton。
  • 在这种情况下不要使用KeyListener,它不适合您想要实现的目标
  • 另外,使用actionCommand 属性而不是强制转换源,它通常更安全
  • @MadProgrammer 你真的是一个疯狂的程序员。我摆脱了JButton 铸造并用动作命令替换了条件并且没有错误。但是我还有KeyListener,可以吗?
  • @asdf “但是我还有 KeyListener,可以吗?” - 不,不是真的。除了JTextField 支持ActionListener 之外,您不能保证 [Enter] 将成为每个平台的“操作”键。作为一般指南,KeyListener 永远不应应用于文本字段 - 还有其他更好的解决方案可供使用

标签: java swing actionlistener


【解决方案1】:

我猜你的ActionListener 正在接收来自多个对象的事件,其中之一是JTextField。当您尝试将此对象强制转换为 JButton 时发生异常:

(JButton) e.getSource();

可能有更好的解决方案,但从您向我们展示的情况来看,防止异常的最简单方法是在强制转换之前检查生成的对象是否为 JButton 的实例:

private class play implements ActionListener{
    public void actionPerformed(ActionEvent e) {
        Object src = e.getSource();
        // Check type before casting
        if (src instanceof JButton) {
            JButton bsrc = (JButton)src;
            if(bsrc.equals(spin)) {
                //do something
            }
        }
    }
}

【讨论】:

  • (e instanceof JButton) 是错误的条件。该事件不会是 JButton 的实例。事件的来源是。
  • 这个“解决”问题,但不能解决根本问题
【解决方案2】:

首先,这个任务不要使用KeyListenerJTextField已经支持ActionListener,你也可以使用JRootPane的“默认按钮”支持,所以有很多更好的解决方案可用。

您还应该利用ActionEvent(和ActionListener)对actionComamnd 的支持,这意味着您不必强制转换源代码,这样更安全并使解决方案更可重用(因为它是解耦的)。

例如...

Play p = new Play();

spin = new JButton("Spin");
spin.setActionCommand(Play.COMMAND);
bet = new JTextField("");
bet.setActionCommand(Play.COMMAND);

spin.addActionListener(p);
bet.addActionListener(p);

//...

private static class Play implements ActionListener {

    public static String COMMAND = "Spin";

    public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().equals(COMMAND)) {
            //do something
        }
    }
}

或者,您可以使用现有的Actions API。这使您可以设计一个独立的工作单元,可以直接应用于许多 Swing 组件(已经支持 ActionListener API),但它们也是可自我配置的、整洁的......

private class SpinAction extends AbstractAction {

    public SpinAction() {
        putValue(NAME, "Spin");
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        // Spin me baby
    }

}

然后简单地应用它......

SpinAction action = new SpinAction();

spin = new JButton(action);
bet = new JTextField("");
bet.setAction(action);

详情请见How to use actions

【讨论】:

  • 如果 OP 想要从事件源访问各种方法,他们必须将源转换为适当的类型。当然,除非它是一个或多个相同类型的侦听器。
  • @wjs - 为什么?有比直接访问ActionEvent 源更好的解决方案,比如使用模型来允许对象之间的信息传递,这既更安全,也更解耦,同时保持了封装的概念。在这种特殊情况下,我可能会想将 JTextField 传递给 SpinAction ,因为事件的来源实际上是无关紧要的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-29
  • 1970-01-01
  • 1970-01-01
  • 2010-09-14
  • 1970-01-01
相关资源
最近更新 更多