Aplikacja okienkowa - zamiana panelu w tym samym oknie

0

Witam!

Tworzę aplikację okienkową, w skrócie - mam okno (klasa Window), w oknie mam panel (poniższa klasa MainMenu) i chciałbym by po kliknięciu w określony obszar panelu nastąpiła zamiana panelu na inny (klasa Game). Niestety gdy próbuję to zrobić w poniższy sposób - czyli w pierwszej kolejności utworzenie obiektu klasy Window:

public Window window;

a następnie wywołanie metody z klasy Window rysującej ten drugi panel:

window.initGame(970, 728);

pojawia się błąd (wkleiłem pod kodem).

Byłby mi ktoś w stanie wyjaśnić co dokładnie tutaj robię źle?
Chociaż jakoś nakierować, rozjaśnić, bo mam totalną pustkę. Googlowałem już w poszukiwaniu porad, ale natknąłem się tylko na sugestię użycia CardLayout, co na razie wolałbym odstawić na bok. Wydaje mi się, że jest jakiś banalny sposób na podmianę panelu w oknie, którego po prostu nie dostrzegam.

Klasa MainMenu

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;

public class MainMenu extends JPanel implements MouseListener
{
    public Window window;

    @Override
    public void mouseClicked(MouseEvent e)
    {
        int x = e.getX();
        int y = e.getY();
        przycisk(x,y);
    }

    @Override
    public void mouseEntered(MouseEvent e) {}

    @Override
    public void mouseExited(MouseEvent e) {}

    @Override
    public void mousePressed(MouseEvent e) {}

    @Override
    public void mouseReleased(MouseEvent e) {}

    public int sWidth; //szerokość panelu
    public int sHeight; //wysokość panelu

    public MainMenu(int width, int height)
    {
        this.sWidth=width;
        this.sHeight=height;

        addMouseListener(this);


    }//koniec konstruktora MainMenu()

    @Override
    protected void paintComponent(Graphics gs)
    {
        Graphics2D g=(Graphics2D)gs;
        //Ustaw tryb lepszej jakości grafiki (wygładzanie/antyaliasing)
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        // Narysuj tło
        g.drawImage(GPars.menuBg, 0, 0, null);
        //Ustaw kolor domyślny
        g.setColor(Color.white);

    }//koniec metody paintComponent

    void przycisk(int x, int y)
    {
        if(x>=336 && x<=636)
        {
            if(y>=188 && y<288)
            {
                System.out.println("TRENING");
            }
            else if(y>=288 && y<388)
            {
                System.out.println("GRAJ");
                window.initGame(970, 728);
            }
            else if(y>=388 && y<488)
            {
                System.out.println("STATYSTYKI");
            }
            else if(y>=488 && y<588)
            {
                System.out.println("ZAKOŃCZ");
                System.exit(2);
            }
            else
            {
                System.out.println("Brak akcji dla tego miejsca!");
            }
        }
        else
        {
            System.out.println("Brak akcji dla tego miejsca!");
        }
    }//koniec metody przycisk
}//koniec klasy MainMenu

Klasa Window

import javax.swing.*;
import java.awt.*;


public class Window extends JFrame
{
    public Window(int width, int height, int x, int y, int m)
    {
        super();
        setTitle("Euroquiz"); //nazwa okna (aplikacji)
        setSize(width, height); //wymiary okna
        setLocation(x,y); //pozycja okna
        setDefaultCloseOperation(3); //zakończ program po zamknięciu okna
        setUndecorated(true);

        if(m==1)
        {
            initMenu(width, height); //wywołaj metodę tworzącą interfejs graficzny menu głównego
        }
        else if(m==2)
        {
            initGame(width, height); //wywołaj metodę tworzącą interfejs graficzny gry
        }


        setVisible(true); //pokaż okno
    }//koniec Window()

    public void initMenu(int width, int height)
    {
        add(new MainMenu(width,height));
    }

    public void initGame(int width, int height)
    {
        add(new Game(width,height));
    }
}

Klasa Game

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JPanel;

public class Game extends JPanel
{
    /** Szerokość pola graficznego gry*/
    public int sWidth;
    /** Wysokość pola graficznego gry*/
    public int sHeight;

    public Game(int width, int height)
    {
        this.sWidth=width;
        this.sHeight=height;
    }//koniec Game()

    @Override
    protected void paintComponent(Graphics gs)
    {
        Graphics2D g=(Graphics2D)gs;
        //Ustaw tryb lepszej jakości grafiki (wygładzanie/antyaliasing)
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        // Narysuj tło
        g.drawImage(GPars.ramka, 0, 0, null);
        g.drawImage(GPars.gameBg, 207, 44, null);
        //Ustaw kolor domyślny
        g.setColor(Color.white);
    }//koniec paintComponent
}//koniec klasy GamePanel

Treść błędu

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
	at MainMenu.przycisk(MainMenu.java:67)
	at MainMenu.mouseClicked(MainMenu.java:15)
	at java.desktop/java.awt.Component.processMouseEvent(Component.java:6581)
	at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3343)
	at java.desktop/java.awt.Component.processEvent(Component.java:6343)
	at java.desktop/java.awt.Container.processEvent(Container.java:2259)
	at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4961)
	at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2317)
	at java.desktop/java.awt.Component.dispatchEvent(Component.java:4793)
	at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4904)
	at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4548)
	at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4480)
	at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2303)
	at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2758)
	at java.desktop/java.awt.Component.dispatchEvent(Component.java:4793)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:766)
	at java.desktop/java.awt.EventQueue.access$500(EventQueue.java:97)
	at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:717)
	at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:711)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:89)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:99)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:739)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:737)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:89)
	at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:736)
	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:199)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
2

Window jest nullem, nie tworzysz go.

public Window window = new Window(1,2,3,4,5);
0

No dobra, parametry dopisane do obiektu, ale wtedy po prostu mi tworzy kolejne okno, nie do końca o to mi chodzi.

Po kliknięciu obszaru "GRAJ", powinien zniknąć panel "MainMenu" i pojawić się panel "Game", w tym samym oknie.

Czyli domyślam się, że poprzez tworzenie kolejnego obiektu klasy Window w klasie MainMenu (pierwszy obiekt utworzony już jest w mainie) nie osiągnę zamierzonego celu. To jak zrealizować tę podmianę panelu?

0

Czyli domyślam się, że poprzez tworzenie kolejnego obiektu klasy Window w klasie MainMenu (pierwszy obiekt utworzony już jest w mainie) nie osiągnę zamierzonego celu.

Nie mam zielonego pojęcia, bo nie znam Twojej metody main a szklana kula jest w zmywarce, której nie posiadam. Po co Ci dwa obiekty tej samej klasy skoro korzystasz z jednego. Pokaż całość.

Ten wątek może Cię zainteresować - polecam także czytać komentarze.

0

Kombinowałem na różne sposoby.
Jest jeszcze klasa GPars, ale tam się nic istotnego nie dzieje (ładowanie grafiki).

Klasa Main (StartGame)

import java.awt.*;

public class StartGame
{
    //Rozmiar okna gry
    public static final int W_WIDTH =970; //734px 970
    public static final int W_HEIGHT=728; //550px 728

    //Pobierz wymiary ekranu
    public static final int S_WIDTH = Toolkit.getDefaultToolkit().getScreenSize().width;
    public static final int S_HEIGHT = Toolkit.getDefaultToolkit().getScreenSize().height;

    //Wyśrodkowanie okna gry - ustalenie współrzędnych lewego górnego narożnika
    public static int xCenter=(S_WIDTH-W_WIDTH)/2;
    //public static int yCenter=(S_HEIGHT-W_HEIGHT)/2;
    public static int yCenter = 0;

    public static void main(String[] args)
    {
        //Załaduj grafikę
        GPars.loadInitialImages();

        //Utworzenie okna gry undecorated (wymiary okna zgodnie z założeniem)
        new Window(StartGame.W_WIDTH, StartGame.W_HEIGHT, StartGame.xCenter, StartGame.yCenter, 1);

    }//koniec konstruktora main
}

1

Spróbuj wyedytować tak:

public MainMenu(int width, int height, Window window) {
        this.sWidth=width;
        this.sHeight=height;
	this.window = window;
 
        addMouseListener(this);
 }//koniec konstruktora MainMenu()

i tak:

    public void initMenu(int width, int height)
    {
        add(new MainMenu(width,height, this));
    }

ale nie obiecuję, że będzie działa. Ewentualnie przerób według linku rzuconego w moim poprzednim poście.

0

Problem rozwiązany - w klasie StartGame utworzyłem globalnie obiekt mojego okna

public static Window w = new Window(W_WIDTH,W_HEIGHT,xCenter,yCenter);

dzięki czemu potem w klasie MainMenu mogłem sobie w następujący sposób wywołać metodę tworzącą drugi panel (metoda initGame jest obecnie u mnie już bezparametrowa, stąd poniższa forma)

StartGame.w.initGame();

i ostatecznie osiągnąłem zamierzony efekt.

Zostawiam dla potomnych, dzięki za pomoc @Burdzi0

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