2014-10-30 2 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

Прочтите исключение - они не просто дают вам всю эту информацию для развлечения, которую вы знаете, это на самом деле ключевой инструмент диагностики. В вашем случае что-то пусто в строке 57 DiceSimulator.java – John3136

+0

Я не знаю, как это прочитать, я новичок. У меня не было бы этой проблемы, если бы это было иначе. – Alex

+0

Какая линия линии 57? – DreadHeadedDeveloper

ответ

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 для creating JFrame applications - у них есть хороший код для примера того, как вы хотите структурировать свою программу.

Причина, по которой я буду использовать статические объявления JLabel, будет ненужной, если вы измените вашу программу на структуру в образце, но по существу, если вы объявите переменную класса, такую ​​как JLabel, каждый экземпляр класса, который является построенные будут иметь собственные версии этих переменных. Поэтому, когда у вас есть метод OUTSIDE конструктора, вы не будете работать над теми же JLabels, даже если они имеют одно и то же имя - снова все это будет неактуально, если вы переработаете свою программу.

Анонимная реализация интерфейса может быть выполнена при создании нового объекта. Для слушателя действий он будет выглядеть примерно так:

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

Я подозреваю, что причина, вы получаете свою ошибку в том, что ваш ActionListener не работал на тот же JLabels, которые были созданы, когда конструктор был назван - который я бы попробовал статические объявления переменных или анонимную реализацию интерфейса

+0

Я забыл компенсировать 1. Я исправил код. int firstRoll = (int) (Math.random() * 6) +1; и т. д. – Alex

+0

Мое другое предложение было бы объявить вас JLabels как статичный, если это не прояснило проблему. –

+0

Также вы можете рассмотреть возможность анонимного выполнения прослушивателя действий INSIDE конструктор diceRoller –

0

Когда я бегу код он бросает исключение при смене значка. Похоже, что изображения, которые вы загружаете, там не существует. Попытайтесь выяснить, каков ваш относительный путь, или чтобы проверить вещи, используют абсолютные исправления.

Напишите комментарий, если вам нужно больше объяснений.

Надеюсь, что смогу помочь.

EDIT

Несколько больше объяснений:

приложение «работает» в определенном месте на жестком диске, когда просто говоря его: D Вы хотите загрузить фотографии. Поскольку те, которые вы ему даете, не начинаются с косой черты, они интерпретируют их как относительные. Это означает, что он смотрит в исполняемый каталог для изображения. Когда он начинается с «/», он интерпретирует как абсолютный путь, который начинается с вашего жесткого диска.

Here объясняется, как вы получаете свой каталог выполнения. Просто используйте

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

при создании объекта и проверке того, что консоль выводит при запуске вашей программы. В папке с именем там вы должны поместить свои фотографии. Это не рекомендуется, но для проверки того, что он работает.

EDIT 2

Не заметил:

Вы получили JLabels dieOne и dieTwo здесь:

private JLabel dieOne; 
private JLabel dieTwo; 

Эти "глобальные" переменные, которые могут быть скрыты местными переменные с тем же именем в методе. Вот где вы допустили ошибку. Вы пишете:

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

Там вы скрыть «глобальный» dieOne и dieTwo, потому что вы объявляете локальные те, с тем же именем. Но они не нужны, потому что вы хотите инициализировать «глобальные» JLabels. Когда вы делаете это так, как сейчас, DieOne и dieTwo в конструкторе уничтожаются при завершении создания объекта, а «глобалы» не получают значения => У них нет адреса, который вызывает исключение NullPointerException при попытке изменить текст. Просто удалите

JLabel dieOne, dieTwo; 

и все должно быть.

Наконец-то надеюсь, что все ясно, и я мог бы помочь.

+0

Спасибо, что не грубый сперва. У меня есть изображения на моем компьютере, поэтому они должны загружаться, если это то, что вы хотите сказать. – Alex

+0

Приложение работает в определенном месте на вашем жестком диске, когда вы говорите это легко: D Вы хотите загрузить изображения. Поскольку те, которые вы ему даете, не начинаются с косой черты, они интерпретируют их как относительные. Это означает, что он смотрит в исполняемый каталог для изображения. Когда он начинается с того, что он интерпретирует как абсолютный путь, который начинается с вашего жесткого диска. Просто спросите, недостаточно ли это достаточно: D – Frozn

+0

Изображения находятся в исполняемом каталоге, если они находятся в той же папке, что и работающая программа, правильно? – Alex