2014-10-30 115 views
-1

我的代码编译和看似运行良好,直到我打了JButton,然后我得到了很多错误。我不确定我做错了什么。代码应该做的是有一个窗口出现,并随机显示两个骰子图像,当点击按钮时。这些图像与我的程序位于同一个目录中,它们被命名为1-6。基本Java Gui错误:为什么JButton会导致错误?

下面的代码:

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) 
+0

阅读异常 - 它们不只是给你所有的信息,你知道它的乐趣,它实际上是一个关键的诊断工具。在你的情况下,DiceSimulator.java第57行的内容为null – John3136 2014-10-30 01:51:27

+0

我不知道如何阅读它,我是一个初学者,如果它是其他任何方式,我都不会遇到这个问题。 – Alex 2014-10-30 01:53:45

+0

第57行是什么? – DreadHeadedDeveloper 2014-10-30 01:54:25

回答

2

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

为了安全起见,请导入了java.util.Random包,并作出这样

进口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); 
    } 

    } 


} 

UPDATE

,你真的想实现的JFrame是要有建立一个JPanel一个构造方法,然后由主方法调用的方式。看看如何在的Java教程中设置示例程序 - 他们已经获得了一些关于如何构建程序的很好的示例代码。

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

当您构建新对象时,可以完成接口的匿名实现。对于一个动作监听它看起来是这样的:

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

我怀疑你是让你的错误的原因是因为你的ActionListener没有对已创建时的构造被称为相同的JLabel工作 - 这这就是为什么我会尝试变量的静态声明或者接口的匿名实现

+0

我忘了补偿1.我纠正了代码。 int firstRoll =(int)(Math.random()* 6)+1;等 – Alex 2014-10-30 02:15:13

+0

我的另一个建议是将JLabels声明为静态的,如果这没有解决问题 – 2014-10-30 02:16:19

+0

另外,你可能想考虑匿名实现动作监听器在diceRoller构造函数中 – 2014-10-30 02:17:41

0

当我跑步时改变图标时,它抛出异常的代码。看起来你正在加载的图像不存在那里。试着找出,你的相对路径是什么,或者测试事物是否使用绝对路径。

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

希望我能帮上忙。

编辑

一些更多的解释:

应用程序“运行”,在您的硬盘驱动器上的特定位置,说这时候很容易:D要加载的图片。由于你给他的路径不是以斜线开始,它将它们解释为相对路径。这意味着,他查找图像的执行目录。当它以“/”开头时,他将解释为绝对路径,该路径从硬盘驱动器开始。

Here解释了如何获得执行目录。刚创建对象时使用

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

,并检查一下控制台输出,当你开始你的程序。在名为的文件夹中,您必须放置照片。这不建议,但要测试它的工作原理。

EDIT 2

没注意到:

你得到了的JLabel dieOne和dieTwo这里:

private JLabel dieOne; 
private JLabel dieTwo; 

这些都是可以通过当地隐藏的 “全局” 变量方法中具有相同名称的变量。那是你犯了一个错误。你写:

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

在那里你隐藏了“全局”dieOne和dieTwo,因为你声明本地的同名。但它们不是必需的,因为你想初始化“全局”JLabels。当你现在这样做时,当完成实例化对象时,dieOne和dieTwo在构造函数中被销毁,而“globals”没有值=>当试图更改文本时,它们没有导致NullPointerException的地址。只要删除

JLabel dieOne, dieTwo; 

和所有应该可以。

最后希望一切都很清楚,我可以帮忙。

+0

谢谢你先不要粗鲁。我的电脑上有图像,所以应该加载,如果这就是你的意思。 – Alex 2014-10-30 01:56:54

+0

应用程序在硬盘驱动器上的特定位置运行时,说起来容易:D您想要加载图片。由于你给他的路径不是以斜线开始,它将它们解释为相对路径。这意味着,他查找图像的执行目录。当它以一个/他开头解释为一个绝对路径时,该路径从您的硬盘驱动器开始。请问是否不够清楚:D – Frozn 2014-10-30 02:03:59

+0

如果图像与正在运行的程序位于相同的文件夹中,则这些图像位于正在执行的目录中,是否正确? – Alex 2014-10-30 02:06:15