0

为这篇长文道歉,但我想尽可能详细,这样人们就有更好的机会理解我想要传达的内容:

好的,所以这个问题的概述是我正在尝试制作一个模拟收银机的程序。(这是一个“有趣”的项目)。我设置的方式是:

CashRegister:启动程序的主类,作为一切的主窗口。

public class CashRegister extends JFrame {
    ...
}

其他类:用作提供主 CashRegister 窗口的不同组件的 JPanel。例子:

public class NorthPanel extends JPanel {
    ...
}

然后在 CashRegister 类中:

add(new NorthPanel(), BorderLayout.NORTH);

等等。基本上,我在 NorthPanel 类中有一个名为 priceField 的 JTextField,它保存用户输入的价格值。我有一个单独的类(键盘),它也扩展了 JPanel 并用作主窗口中心的数字键盘。在 CashRegister 中:

add(new NorthPanel(), BorderLayout.NORTH);
add(new Keypad()); // (default for BorderLayout is CENTER)

我遇到的一个问题是我创建了一个类,EventHandler,作为整个程序的侦听器类,因为每个 JPanel 类(例如 NorthPanel 和 Keypad)中都有需要相互通信的组件; 用户按下键盘按钮,NorthPanel 中的价格字段需要知道按下了键盘中的哪个键。

我不知道问题是否来自这些组件来自不同的类,因此引用方式不同,或者是什么。所有的类都在同一个目录中,我使用的是 NetBeans,它都是同一个包的一部分。

在我的 EventHandler 类中,我创建了几个不同的构造函数,以便能够从不同的类中传入所有需要相互通信的组件。例如:

public class EventHandler implements ActionListener {
    private JTextField priceField;
    private JButton[][] keypad;

    public EventHandler(JTextField priceField) {
        this.priceField = priceField;
    }

    public EventHandler(JButton[][] keypad) {
        this.keypad = keypad;
    }
}

在我的 NorthPanel 类中,我首先实例化 priceField,对其进行配置(设置字体等)并说:

EventHandler e = new EventHandler(priceField);

在我尝试将 priceField 传递给我的侦听器类时。

然后在键盘类中,我说:

EventHandler e = new EventHandler(keypad);
for(int i = 0; i < 4; i++) {
    for(int j = 0; j < 3; j++) {
        keypad[i][j].addActionListener(e);
    }
}

然后在 EventHandler 类中,通过这些变量:

public void actionPerformed(ActionEvent e) {
    for(int i = 0; i < 4; i++) {
        for(int j = 0; j < 3; j++) {
            if(keypad[i][j] == e.getSource()) {
                // call a custom method to append the numbers to the text field
            }
        }
    }
}

正是在这一点上,我得到了 NullPointerException。我不知道为什么,但我猜这是因为监听器对象来自不同的类并使用不同的构造函数,因为我必须从每个需要相互通信的类中传递不同的对象。不过,我不是 100% 确定。有没有办法解决这个问题,还是我做错了什么?

4

1 回答 1

0

您应该让CashRegister处理所有用户输入,因为它是应用程序的主框架(它扩展了JFrame)。对于子面板,在您覆盖的 keyPressed 方法的主体内创建一个方法,例如aKeyWasPressed( int keyCode ),该方法将从您的框架中调用。

此外,将 JFrame 设置为可聚焦,并最好使其他面板无法聚焦setFocusable(false);

这是CashRegister的示例代码:

public class CashRegister extends JFrame implements KeyListener
{
    private NorthPanel northPanel;
    private Keypad keypad;

    public CashRegister ()
    {
        this.setFocusable(true);
        this.addKeyListener(this);
        northPanel = new NorthPanel();
        keypad = new Keypad();

        /* Your code ... */
    }

    @Override
    public void keyTyped(KeyEvent ke) 
    {
        /*Do nothing*/
    }

    @Override
    public void keyPressed(KeyEvent ke) 
    {
        northPanel.aKeyWasPressed( ke.getKeyCode() );
        keypad.aKeyWasPressed( ke.getKeyCode() );
    }

    @Override
    public void keyReleased(KeyEvent ke) 
    {
        /*Do nothing*/
    } 
}


注意:要区分按下了哪个键,在面板的aKeyWasPressed方法中,您可以执行以下操作:

private void aKeyWasPressed(int code)
{
    if(code == KeyEvent.VK_A)
    {
        /*If its letter 'A', do this...*/
    }
}

同样,有很多方法可以做到这一点,但在我看来,让 Frame 本身处理所有用户输入是大多数情况下的最佳实践,主要是在处理多个面板时。

于 2013-09-04T04:57:04.297 回答