NullPointerException, wszystko wywołane

0

Klasa Main rozszerzająca JFrame w metodzie public static void main(String[] args) wywołuje samą siebie (Main main = new Main()). W klasie tej znajduje się linijka private MainMenuGUI MainMenu = new MainMenuGUI(this). Klasa MainMenuGUI (rozszerzająca JPanel) wymaga klasy Main, by móc wywoływać metodę Action. Gdy w argumentach Action poda się 1, do ramki Main powinien zostać dodany panel MainMenuGUI, jednak zamiast tego w linijce this.add(MainMenu) zwracany jest NullPointerException.
Po podaniu 2 (mającego dodać do ramki panel OptionMainMenuGUI) również zwracany jest NullPointerException.

Metoda Action:

public void Action(int p) {
        if (actualPanel != null) {
            this.remove(actualPanel);
        }
        switch (p) {
            case 1:
                this.add(MainMenu);
                actualPanel = MainMenu;
            case 2:
                this.add(OptionMainMenu);
                actualPanel = MainMenu;
            default:
                System.exit(1);
        }
        this.repaint();
    }
    public static final int MAIN_MENU = 1;
    public static final int OPTION_MAIN_MENU = 2;

Tworzenie zmiennych - paneli w klasie Main:

private MainMenuGUI MainMenu = new MainMenuGUI(this);
    private OptionMainMenuGUI OptionMainMenu = new OptionMainMenuGUI(this);
0

private MainMenuGUI MainMenu = new MainMenuGUI(main);
private OptionMainMenuGUI OptionMainMenu = new OptionMainMenuGUI(main);
chodzi o tego main który: Main main = new Main();
No chyba że czegoś nie zrozumiałem z twojego postu.

0

W jakiej klasie jest metoda Action? Pierwsza hipoteza jest taka: masz w tej właśnie klasie pole o nazwie MainMenu, i pole to nie jest inicjowane (zawiera null).

0

W klasie Main.

Chyba że wewnątrz samej klasy zostawić tylko private MainMenuGUI MainMenu; a później:

public static void main(String[] args) {
Main main = new Main();
...
MainMenu = new MainMenuGUI(main);
}

Ale wtedy zmienne będą musiały być statyczne.

0

Sprawdziłem. Wcześniej nie wyświetlała się nawet ramka, teraz ramka się wyświetla. Nadal jednak jest NullPointerException i brak komponentów z panelu.

0

Jak dalej będziesz cedzić fragmentami swój super tajny kod to może do końca następnego roku pokażesz jednak fragment w którym masz ten błąd ;P

0

Daj cały kod, to może coś poradzimy.

0

"Cały kod"... czyli na stan aktualny 255 linijek? Powaga? Proszę was bardzo.

BTW, wstawiłem tylko ten kod, który jest odpowiedzialny za błąd.

Main.java

package mario;

import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JPanel;
import mario.gui.MainMenuGUI;
import mario.gui.OptionMainMenuGUI;
import mario.options.ArgumentsInterpreter;

public class Main extends JFrame {
    public static void main(String[] args) {
          Main main = new Main();
          main.runFrame(args);
    }
    private void runFrame(String[] args) {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Dimension dim = new Dimension(Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height);
        int var1 = 0;
        for(int i = 0; i < dimensions.length; i++) {
            if (dimensions[i].equals(dim)) {
                this.setSize(dim);
                this.setUndecorated(true);
            }
            else {
                var1++;
            }
        }
        if (var1 == dimensions.length) {
            this.setSize(dimensions[0]);
            this.setUndecorated(false);
        }
        this.setResizable(false);
        this.setTitle("Mario Social");
        this.setVisible(true);
        argint.Interpret(args, this);
    }
    public void Action(int p) {
        if (actualPanel != null) {
            this.remove(actualPanel);
        }
        switch (p) {
            case 1:
                this.add(MainMenu);
                actualPanel = MainMenu;
            case 2:
                this.add(OptionMainMenu);
                actualPanel = MainMenu;
            default:
                System.exit(1);
        }
        this.repaint();
    }
    public static final int MAIN_MENU = 1;
    public static final int OPTION_MAIN_MENU = 2;
    public void setFullScreen(boolean b) {
        this.dispose();
        if (b) {
            this.setSize(Toolkit.getDefaultToolkit().getScreenSize());
        }
        else {
            this.setSize(dimensions[0]);
        }
        this.setUndecorated(b);
        this.setVisible(true);
    }
    private JPanel actualPanel;     
    public final Dimension[] dimensions = {
        new Dimension(800, 600),
        new Dimension(1280, 800),
        new Dimension(1400, 1050),
        new Dimension(1024, 600),
        new Dimension(1600, 1200),
        new Dimension(1600, 900),
        new Dimension(2048, 1536)
    };
    private MainMenuGUI MainMenu = new MainMenuGUI();
    private OptionMainMenuGUI OptionMainMenu = new OptionMainMenuGUI(this);
    private ArgumentsInterpreter argint = new ArgumentsInterpreter();
}

MainMenuGUI.java:

package mario.gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
import mario.Main;

public class MainMenuGUI extends JPanel {
    public MainMenuGUI() {}
    public void setFrame(Main f) {
        this.f = f;
        this.run();
        this.setAccess();
        f.Action(Main.MAIN_MENU);
    }
    private void run() {
        this.add(spButton);
        this.add(mpButton);
        this.add(editorButton);
        this.add(optionButton);
        this.add(exitButton);
        Listener l = new Listener();
        spButton.addActionListener(l);
        mpButton.addActionListener(l);
        editorButton.addActionListener(l);
        optionButton.addActionListener(l);
        exitButton.addActionListener(l);
    }
    private void setAccess() {
        spButton.setEnabled(false);
        mpButton.setEnabled(false);
        editorButton.setEnabled(false);
        optionButton.setEnabled(true);
        exitButton.setEnabled(true);
    }
    private class Listener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == exitButton) {
                System.exit(0);
            }
            if (e.getSource() == optionButton) {
                f.Action(Main.OPTION_MAIN_MENU);
            }
        } 
    }
    private Main f;
    private JButton exitButton = new JButton("Wyjście z gry");
    private JButton optionButton = new JButton("Opcje");
    private JButton spButton = new JButton("Gra jednoosobowa");
    private JButton mpButton = new JButton("Gra wieloosobowa");
    private JButton editorButton = new JButton("Edytor");
}

0

OptionMainMenuGUI.java:

package mario.gui;

import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import mario.Main;

public class OptionMainMenuGUI extends JPanel {
    public OptionMainMenuGUI(Main m) {
        f = m;
    }
    private void run() {
        Box allComponents = Box.createVerticalBox();
        allComponents.add(fullScreen);
        
        Box size = Box.createHorizontalBox();
        size.add(new JLabel("Ustal rozmiar ekranu"));
        size.add(screenSize);
        
        allComponents.add(size);
        allComponents.add(Box.createGlue());
        
        Box end = Box.createHorizontalBox();
        end.add(save);
        end.add(exit);
        
        allComponents.add(end);
        this.add(allComponents);
        this.repaint();
    }
    private Main f;
    private JButton fullScreen = new JButton("Włącz/Wyłącz pełny ekran");
    private JSlider screenSize = new JSlider(0, 6, 0);
    private JButton save = new JButton("Zapisz i wróć do menu");
    private JButton exit = new JButton("Anuluj");
}

ArgumentsInterpreter.java:

package mario.options;

import mario.Main;

public class ArgumentsInterpreter {
    public void Interpret(String[] args, Main m) {
        if (args != null) {
            for (int i = 0; i < args.length; i+=2) {
                if (args[i].equals("-fs")) {
                    m.setFullScreen(Boolean.parseBoolean(args[i+1]));
                }
                if (args[i].equals("-s")) {
                    m.setSize(Integer.parseInt(args[i+1]), Integer.parseInt(args[i+2]));
                }
            }
        }
    }
}

Dimension.java (moja delikatna przeróbka java.awt.Dimension):

package mario;

public class Dimension extends java.awt.Dimension {
    public Dimension() {
        super();
    }
    public Dimension(Dimension d) {
        super(d);
    }
    public Dimension(int x, int y) {
        super(x, y);
    }
    public boolean equals(Object ob) {
        if (ob == this) {
            return true;
        }
        if (ob == null) {
            return false;
        }
        if (this.getClass() != ob.getClass()) {
            return false;
        }
        Dimension dim = (Dimension)ob;
        return dim.height == this.height &&
                dim.width == this.width;
    }
}
0

W klasie Main w metodzie Action spróbowałem zamiast dodawania/usuwania paneli pokazywać je i ukrywać, ale to nadal zwraca NPEx.

0

Wklej całego stack-trace'a dlatego NullPointerException.

0
Exception in thread "main" java.lang.NullPointerException
	at java.awt.Container.addImpl(Container.java:1086)
	at java.awt.Container.add(Container.java:998)
	at javax.swing.JFrame.addImpl(JFrame.java:562)
	at java.awt.Container.add(Container.java:410)
	at mario.Main.Action(Main.java:50)
	at mario.gui.MainMenuGUI.<init>(MainMenuGUI.java:21)
	at mario.Main.<init>(Main.java:83)
	at mario.Main.main(Main.java:19)
Java Result: 1
0

Trzeba od każdego wiersza odjąć 7, bo w kodzie źródłowym nie podałem komentarzy.

0

U mnie ten kod uruchamia się bez NPE, pokazuje puste okienko w fullscreenie.

0

Spróbuj może w main() dodać SwingUtilities.invokeLater(...) ? Dla aplikacji z GUI w SWINGu to jest poprawna metoda ich uruchamiania.

0

Po implementacji i delikatnej przeróbce, by InvokeLater działało, nadal NPEx. Również Windows 7 i Java 7. Jeśli to coś zmienia, to NetBeans IDE 7.2

0

Ja nie wiem czy to może być problem u Ciebie, ale u mnie przez to nie chciało się w ogóle nic wyświetlić (czytaj to: wyświetlić puste okienko, bez żadnych paneli na framie). W metodzie Action w switchu po każdym case w tym wypadku raczej powinno być break, bo bez tego, jeśli wykona się pierwszy case, to wykona się każdy kolejny (również default) dopóki nie napotka właśnie break'a, albo po prostu switch się nie skończy.
Tak czy inaczej mi bez tego po prostu nic się nie pokazywało. Teraz będę próbował zrobić krok kolejny, czyli pokazanie się dowolnego panelu, bo na razie mam puste okienko.

Nawiasem mówiąc (bez urazy dla Ciebie) ten kod GUI jest trochę dla mnie mało czytelny i być może dlatego nie potrafię znaleźć problemu. Może to moja ułomność, a może trzeba przejść specjalne szkolenie, ale ja zawsze miałem problemy ze Swingiem (nigdy nie mogłem się z nim dogadać kiedy pisałem z palca) i czasami jakaś kolejność wywołania funkcji na danym panelu, czy innym komponencie powodowała że program się nie uruchamiał, albo sypał błędami (często właśnie NPEx). Kolejność, która w moim odczuciu nie powinna mieć wpływu na siebie, niestety miała. Może i tutaj masz podobnie, może warto się zainteresować sposobem w jaki tworzysz kod GUI, może właśnie zanim tworzysz rzeczywisty obiekt, wywołuje się pod spodem Action() i stąd NPEx. Dlatego zawsze używam albo graficznego builder'a (pod Eclipse'a chyba najlepszy to WindowBuilder, może pod NetBeansa też to jest) i dzięki temu nie ma jakichś niedociągnięć, a i można się douczyć pisania ładnego kodu pod Swinga. Albo druga opcja, używanie biblioteki SWT (taka reklama tej natywnej biblioteki), gdzie nigdy nie miałem problemów ze Swinga, a nawet uważam że jest bardziej logicznie stworzona i mi osobiście się przyjemniej w niej kodzi pod Java. Sorry za spam, ale jestem dość mocno cięty na Swinga za wiele godzin jakie straciłem nad kodem, który nie powinien mieć wpływu, ale to tylko wiedziałem ja, Swing wiedział swoje.

// EDIT ----------

Nie jestem w stanie wyjaśnić co jest nie tak w Twoim kodzie (patrz wyżej, nie rozumiem pewnych zachowań Swinga, więc pewnie dlatego) ale w załączniku masz poprawiony po mojemu Twój kod i działa normalnie. Może analiza tego co zrobiłem Tobie pomoże. Generalnie pewne wywołania przerzuciłem do konstruktorów klas paneli MainMenuGUI i OptionMainMenuGUI, ale nie sądzę żeby to miało wpływ (ale jak ponarzekałem sobie wyżej, ja po Swingu wszystkiego się mogę spodziewać). Natomiast wydaje mi się, że klasa Main mogła spowodować poprawę. To co zrobiłem, to stworzyłem jeden główny panel (Twój actualPanel), który ustawiam na frame'a za pomocą setContentPane(). I na ten panel nakładam dwa powyższe i zaczyna działać. I teraz w Action w zależności od parametru ustawiam odpowiednie Visible na menu główne lub opcje. Niestety, nie potrafię wyjaśnić i zrozumieć co w Twoim kodzie jest nie tak, bo u mnie Twój kod w ogóle się nie uruchamiał. Po prostu się włączał i od razu kończył, zanim cokolwiek wyświetlił (przez switcha który nie miał breaków i przez to trafiał na System.exit(1). A po tej poprawce pokazywał puste okienko).

0

No to ja państwa zaskoczę: kod działa W 100% - nawet panele wyświetla :)

Co do break w switchu, to kiedyś tworząc switcha z break'ami netbeans wyświetlał błąd, a po usunięciu breaków kod działał poprawnie. Pomyślałem więc, że Java weszła w stan, w którym break samoistnie "łączy się" z case, i... przestałem używać break. Teraz jednak netbeans nie wyświetla błędów, a ja głupi będę musiał uczyć się używać break.

Dzięki wielkie, panowie. Mimo wszystko, dział Newbie do mnie pasuje :D

1 użytkowników online, w tym zalogowanych: 0, gości: 1