基本Java Gui错误:为什么JButton会导致错误?

时间:2014-10-30 01:48:55

标签: java user-interface logic runtime-error

我的代码编译并且看起来运行良好,直到我点击JButton然后我收到很多错误。我不确定我做错了什么。代码应该做的是有一个窗口出现并在单击按钮时随机显示两个骰子图像。这些图像与我的程序位于同一目录中,它们被命名为1-6。

以下是代码:

import java.lang.Math;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DiceSimulator extends JFrame
{
  private JLabel dieOne;
  private JLabel dieTwo;
  public DiceSimulator()
  {
    setTitle("Dice Simulator");
    JLabel dieOne, dieTwo;
    dieOne = new JLabel();
    dieTwo = new JLabel();
    JButton button = new JButton("Roll the Dice");
    button.addActionListener(new buttonListener());  
    setLayout(new BorderLayout());
    JPanel panel = new JPanel();
    panel.add(button, BorderLayout.SOUTH);
    panel.add(dieOne);
    panel.add(dieTwo);
    add(panel);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    pack();
    setVisible(true);
    }
  private class buttonListener implements ActionListener
  {
    public void actionPerformed(ActionEvent e)
    {
      ImageIcon one = new ImageIcon("1.jpg"); 
      ImageIcon two = new ImageIcon("2.jpg"); 
      ImageIcon three = new ImageIcon("3.jpg"); 
      ImageIcon four = new ImageIcon("4.jpg"); 
      ImageIcon five = new ImageIcon("5.jpg"); 
      ImageIcon six = new ImageIcon("6.jpg"); 
      int firstRoll = (int)(Math.random()*6)+1;
      int secondRoll = (int)(Math.random()*6)+1;
      switch(firstRoll)
      {
        case 1: dieOne.setIcon(one);
        dieOne.setText(null);
        break;
        case 2: dieOne.setIcon(two);
        dieOne.setText(null);
        break;
        case 3: dieOne.setIcon(three);
        dieOne.setText(null);
        break;
        case 4: dieOne.setIcon(four);
        dieOne.setText(null);
        break;
        case 5: dieOne.setIcon(five);
        dieOne.setText(null);
        break;
        case 6: dieOne.setIcon(six);
        dieOne.setText(null);
        break;
      }
      switch(secondRoll)
      {
        case 1: dieTwo.setIcon(one);
        dieTwo.setText(null);
        break;
        case 2: dieTwo.setIcon(two);
        dieTwo.setText(null);
        break;
        case 3: dieTwo.setIcon(three);
        dieTwo.setText(null);
        break;
        case 4: dieTwo.setIcon(four);
        dieTwo.setText(null);
        break;
        case 5: dieTwo.setIcon(five);
        dieTwo.setText(null);
        break;
        case 6: dieTwo.setIcon(six);
        dieTwo.setText(null);
        break;
      }
    }
  }
  public static void main(String[] args)
  {
    new DiceSimulator();
  }
}

这是我点击按钮时出现的错误:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at DiceSimulator$buttonListener.actionPerformed(DiceSimulator.java:57)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$200(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

2 个答案:

答案 0 :(得分:2)

我不认为您正确生成随机数。当我运行类似的代码来生成随机数时,我会在随机数中包含一堆零,您不会使用switch语句处理这些零。

为了安全起见,导入java.util.Random包,并创建一个像

这样的对象

import java.util.Random;

public class testRandom{

  public static void main (String [] args){
    Random rg = new Random();
   int x;
   for(int i = 0; i < 100; i++){
    x = rg.nextInt(6) + 1;
    System.out.println(x);
   }

  }


}

更新

您真正想要实现JFrame的方法是使用构造函数方法构建JPanel,然后由main方法调用。看看如何在creating JFrame applications的Java教程中设置示例程序 - 他们在那里有一些很好的示例代码,用于构建程序。

如果您将程序更改为示例中的结构,那么我使用静态JLabel声明的原因将是不必要的,但实质上如果您声明类变量(如JLabel),则该类的每个实例都是构造将具有自己的那些变量的版本。因此,当你有一个构造函数的OUTSIDE方法时,你就不会在相同的JLabel上工作,即使它们具有相同的名称 - 如果你重新编写程序,所有这些都将无关紧要。

在构建新对象时,可以完成接口的匿名实现。对于动作监听器,它看起来像:

JButton button = new JButton("Click me!");
button.addActionListener(new ActionListener(){
   public void (ActionPerformed ap){
     //DO SOMETHING ON CLICK
  }
});

我怀疑你收到错误的原因是因为你的actionListener没有处理在调用构造函数时创建的相同JLabel - 这就是我尝试静态声明的原因。变量,或接口的匿名实现

答案 1 :(得分:0)

当我运行代码时,它会在更改图标时抛出异常。看起来你正在加载的图像并不存在。试着找出你的相对路径,或者用绝对的方法来测试事物。

如果您需要更多解释,请撰写评论。

希望我能提供帮助。

修改

更多解释:

应用程序&#34;运行&#34;在硬盘驱动器上的特定位置,说起来容易:D您想要加载图片。你给他的那些小贴士不是从斜线开始,而是将它们解释为相对的角色。这意味着,他在执行目录中查找图像。当它以&#34; /&#34;开始时他将其解释为一条绝对的道路,从你的硬盘开始。

Here解释了如何获取执行目录。只需使用

System.out.println(this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath());

创建对象时,检查启动程序时控制台输出的内容。在那里命名的文件夹中,你必须放置你的照片。这不是推荐的,而是测试它的作用。

编辑2

没有注意到:

你有JLabels dieOne和dieTwo:

private JLabel dieOne;
private JLabel dieTwo;

这些是&#34;全球&#34;可以由方法中具有相同名称的局部变量隐藏的变量。多数民众赞成你犯了一个错误。你写道:

public DiceSimulator() {
    setTitle("Dice Simulator");
    JLabel dieOne, dieTwo;
    [...]

你隐藏了&#34;全球&#34; dieOne和dieTwo因为你声明了具有相同名称的本地的。但它们并不是必需的,因为你想初始化&#34;全球&#34; Jlabel之下。当你现在这样做时,构造函数中的dieOne和dieTwo在完成实例化对象和&#34;全局&#34;时会被销毁。没有价值=&gt;在尝试更改文本时,它们没有导致NullPointerException的地址。只需删除

即可
JLabel dieOne, dieTwo;

一切都应该可以。

最后希望一切都清楚,我可以提供帮助。