为长篇文章道歉,但我希望尽可能详细,以便人们更好地理解我要传达的内容:
好的,所以这个问题的概述是我正在尝试制作一个模拟收银机的程序。 (这是一个“有趣”的项目)。我设置的方式是:
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。我不知道为什么,但我的猜测是因为监听器对象来自不同的类并使用不同的构造函数,因为我必须从每个需要相互通信的类传入不同的对象。我不是百分百肯定的。有办法解决这个问题,还是我做错了什么?
答案 0 :(得分: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本身处理所有用户输入是大多数情况下的最佳实践,主要是在处理多个面板时。