Alain Cruz Alain Cruz - 6 months ago 10
Java Question

JAVA multiple screens

I am building a simple 1024 game. The main interface (or screen) is finished and working properly, but I am trying to add another interface (or screen) which is the main menu.

I am trying to do so, by adding two containers to the same JFrame; but for some reason the first container cannot be seen, even though the last one is set to be hiding [setVisible(false)].

I have tried other methods, like having a Container component and adding JPanels to it's

CENTER
,
WEST
and
EAST
spaces and toggle the visibility between them, which works, but I could tell that this sound like a bad programming practice, since I couldn't add more than 3 screens using this method.

Is there a specific way or correct way to do what is a basic program process?

Here is the code for my GUI interface class, I have 3 other classes with the game implementations. Also, my main language is Spanish, so most of the references are written in Spanish :(. I hope my code is clear enough.

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

class Interfaz extends JFrame
{
private Controlador controlador;
private JOptionPane mensajeOpcion;

private Container contenedorJuego;
private Container contenedorMenu;


private JButton newGame;
private JButton startGame;

private JLabel recordLabel;
private JLabel puntajeLabel;
private JLabel[] labelFichas;
private JLabel marcador;

private JPanel tableroPanel;
private JPanel marcadorPanel;
private JPanel mandosPanel;

private final Color COLOR_0 = new Color(0,153,153);
private final Color COLOR_BG_FRAME = new Color(240,233,210);
private final Color COLOR_MARCADOR = new Color(163,155,127);
private final Color COLOR_MARCADOR_LABEL = new Color(240,233,210);
private final Color COLOR_CONTENIDO_LABELS = new Color(255,255,204);
private final Font FONT_PRINCIPAL = new Font("Helvetica",Font.PLAIN,24);
private final Font FONT_SECUNDARIA = new Font("Helvetica",Font.PLAIN,14);
private final Font FONT_MARCADOR = new Font("Impact",Font.BOLD,26);
private final String[] RESULTADO_FINAL = {"¡Volver a Jugar!","¡Salir!"};

private final ImageIcon FLECHA_ARRIBA = new ImageIcon(this.getClass().getResource("/imagenes/Flecha-Arriba.png"));
private final ImageIcon FLECHA_DERECHA = new ImageIcon(this.getClass().getResource("/imagenes/Flecha-Der.png"));
private final ImageIcon FLECHA_IZQUIERDA = new ImageIcon(this.getClass().getResource("/imagenes/Flecha-Izq.png"));
private final ImageIcon FLECHA_ABAJO = new ImageIcon(this.getClass().getResource("/imagenes/Flecha-Abajo.png"));

/**
* Controlador de la clase que se encarga de inicializar el objeto Interfaz
*/

public Interfaz(Controlador elControlador)
{
controlador = elControlador;
mensajeOpcion = new JOptionPane();

this.initComponent();
this.makeMarcador(marcadorPanel);
this.makeTablero(tableroPanel);
this.makeMenu();
this.agregarContenidoContenedorJuego();
this.makeMandos(mandosPanel);
this.configurar();
}

/**
* Metodo que se encarga de inicializar los componentes del objeto interfaz
*/

public void initComponent()
{
contenedorJuego = new Container();
contenedorJuego.setLayout(new BorderLayout());

contenedorMenu = new Container();

newGame = new JButton("New Game");
startGame = new JButton("Iniciar");
recordLabel = new JLabel("0");
puntajeLabel = new JLabel("0");
labelFichas = new JLabel[16];
marcador = new JLabel("0");

marcadorPanel = new JPanel();
marcadorPanel.setLayout(new BorderLayout());
marcadorPanel.setBorder(BorderFactory.createEmptyBorder(20, 30, 0, 30));
marcadorPanel.setBackground(COLOR_BG_FRAME);
marcadorPanel.setOpaque(true);

tableroPanel = new JPanel();
tableroPanel.setLayout(new GridLayout(4,4,5,5));
tableroPanel.setBorder(BorderFactory.createEmptyBorder(20, 30, 0, 30));
tableroPanel.setBackground(COLOR_BG_FRAME);
tableroPanel.setOpaque(true);

mandosPanel = new JPanel();
mandosPanel.setLayout(new FlowLayout());
mandosPanel.setBorder(BorderFactory.createEmptyBorder(20, 30, 20, 30));
mandosPanel.setBackground(COLOR_BG_FRAME);
mandosPanel.setOpaque(true);
}

public void makeMenu()
{
startGame.setActionCommand("Iniciar");
contenedorMenu.add(startGame);
//this.add(contenedorMenu);
}

/**
* Metodo que recibe un JPanel y le agrega los componentes necesarios
* para poder mostrar el marcador con los puntajes correspondientes a
* cada juego
*/

public void makeMarcador(JPanel panel)
{
Box panelIzquierdo = new Box(1);
panelIzquierdo.setBorder(BorderFactory.createEmptyBorder(13, 13, 13, 13));
panelIzquierdo.setBackground(COLOR_0);
panelIzquierdo.setOpaque(true);

Box panelDerecho = new Box(1);
panelDerecho.setBorder(BorderFactory.createEmptyBorder(13, 25, 13, 25));
panelDerecho.setBackground(COLOR_0);
panelDerecho.setOpaque(true);

JButton nuevoJuego = new JButton("NUEVO JUEGO");
nuevoJuego.setFocusable(false);
nuevoJuego.setBackground(COLOR_MARCADOR);
nuevoJuego.setForeground(Color.white);
nuevoJuego.setOpaque(true);
nuevoJuego.setBorderPainted(false);
nuevoJuego.setFont(FONT_SECUNDARIA);
nuevoJuego.setCursor(new Cursor(Cursor.HAND_CURSOR));
nuevoJuego.setActionCommand("Nuevo");
nuevoJuego.addActionListener(controlador);

JLabel marcadorTexto = new JLabel("MARCADOR");
marcadorTexto.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
marcadorTexto.setAlignmentX(Component.CENTER_ALIGNMENT);
marcadorTexto.setFont(FONT_SECUNDARIA);
marcadorTexto.setForeground(Color.white);

marcador.setFont(FONT_MARCADOR);
marcador.setAlignmentX(Component.CENTER_ALIGNMENT);
marcador.setForeground(Color.white);

JLabel recordTexto = new JLabel("RECORD");
recordTexto.setAlignmentX(Component.CENTER_ALIGNMENT);
recordTexto.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
recordTexto.setFont(FONT_SECUNDARIA);
recordTexto.setForeground(Color.white);

recordLabel.setFont(FONT_MARCADOR);
recordLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
recordLabel.setForeground(Color.white);

JPanel panelPuntaje = new JPanel();
panelPuntaje.setLayout(new FlowLayout());
panelPuntaje.setBackground(COLOR_BG_FRAME);
panelPuntaje.setOpaque(true);

panelDerecho.add(recordTexto);
panelDerecho.add(recordLabel);

panelIzquierdo.add(marcadorTexto);
panelIzquierdo.add(marcador);

panelPuntaje.add(panelIzquierdo);
panelPuntaje.add(panelDerecho);

panel.add(nuevoJuego,BorderLayout.CENTER);
panel.add(panelPuntaje,BorderLayout.EAST);
}

/**
* Metodo que recibe un JPanel y le agrega todos los componentes necesarios para que pueda mostrar
* el tablero con el cual el programa se comunicara con el usuario
*/

public void makeTablero(JPanel panel)
{
for (int contador = 0; contador<16; contador++)
{
labelFichas[contador] = new JLabel();
labelFichas[contador].setHorizontalAlignment(SwingConstants.CENTER);
labelFichas[contador].setBackground(COLOR_0);
labelFichas[contador].setOpaque(true);
labelFichas[contador].setForeground(Color.white);
labelFichas[contador].setFont(FONT_MARCADOR);
tableroPanel.add(labelFichas[contador]);
}
}

/**
* Metodo que recibe un JPanel que le agregar los botones, que conceptualizan los mandos
* del juego, para que el jugador pueda comunicarse con el programa
*/

public void makeMandos(JPanel panel)
{
JButton botonArriba = new JButton();
botonArriba.setActionCommand("Arriba");
this.aagregarEfectosBotonosMandos(botonArriba,FLECHA_ARRIBA);
botonArriba.setMnemonic(KeyEvent.VK_UP);
botonArriba.addKeyListener(controlador);

JButton botonDerecha = new JButton();
botonDerecha.setActionCommand("Derecha");
this.aagregarEfectosBotonosMandos(botonDerecha,FLECHA_DERECHA);
botonDerecha.setMnemonic(KeyEvent.VK_RIGHT);
botonDerecha.addKeyListener(controlador);

JButton botonIzquierda = new JButton();
botonIzquierda.setActionCommand("Izquierda");
this.aagregarEfectosBotonosMandos(botonIzquierda,FLECHA_IZQUIERDA);
botonIzquierda.setMnemonic(KeyEvent.VK_LEFT);
botonIzquierda.addKeyListener(controlador);

JButton botonAbajo = new JButton();
botonAbajo.setActionCommand("Abajo");
this.aagregarEfectosBotonosMandos(botonAbajo,FLECHA_ABAJO);
botonAbajo.setMnemonic(KeyEvent.VK_DOWN);
botonAbajo.addKeyListener(controlador);

panel.add(botonIzquierda);
panel.add(botonArriba);
panel.add(botonDerecha);
panel.add(botonAbajo);
}

/**
* Metodo que recibe un objeto JButton y un objeto ImageIcon y le agrega los efectos necesarios
* para que tengan los diseños que queremos que tengán
*/

private void aagregarEfectosBotonosMandos(JButton boton,ImageIcon imagen)
{
boton.addActionListener(controlador);
boton.setCursor(new Cursor(Cursor.HAND_CURSOR));
boton.setBackground(COLOR_0);
boton.setOpaque(true);
boton.setBorderPainted(false);

Image newImagen = imagen.getImage().getScaledInstance(50,50,Image.SCALE_SMOOTH);
ImageIcon imagenDimensionada = new ImageIcon();
imagenDimensionada.setImage(newImagen);
boton.setIcon(imagenDimensionada);
}

private void agregarContenidoContenedorJuego()
{
contenedorJuego.add(marcadorPanel,BorderLayout.NORTH);
contenedorJuego.add(tableroPanel,BorderLayout.CENTER);
contenedorJuego.add(mandosPanel,BorderLayout.SOUTH);
this.add(contenedorJuego);
contenedorJuego.setVisible(true);
}

public void cambiarContenedor()
{
contenedorJuego.setVisible(true);
}

private void configurar()
{
this.setTitle("MEGA 2048");
this.setLocationRelativeTo(null);
this.setSize(450,650);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}

public void iniciar()
{
this.moverTablero();
this.setVisible(true);
}

public void setMarcador(int marcadorNumero)
{
marcador.setText(""+marcadorNumero);
}

public void setRecord(int recordNumero)
{
recordLabel.setText(""+recordNumero);
}

public void moverTablero()
{
int indiceLabel = 0;
int valorTemporal = 0;
for (int contadorX = 0; contadorX<4; contadorX++)
{
for (int contadorY = 0; contadorY<4; contadorY++)
{
valorTemporal = controlador.getValorFicha(contadorX,contadorY);
if (valorTemporal==0)
{
labelFichas[indiceLabel].setText("");
labelFichas[indiceLabel].setBackground(controlador.getColorFicha(contadorX,contadorY));
}
else
{
labelFichas[indiceLabel].setText(""+valorTemporal);
labelFichas[indiceLabel].setBackground(controlador.getColorFicha(contadorX,contadorY));
}
indiceLabel++;
}
}
this.repaint();
}

public void nuevaFichaTablero()
{
this.repaint();
}

public int anunciarResultado(int opcion)
{
int resultado = 0;
switch(opcion)
{
case 1:
resultado = mensajeOpcion.showOptionDialog(this,"¡Ganaste!\nTu record es de: " + controlador.getRecord() + "\nTu puntaje es de: " + controlador.getPuntaje(),"2048",mensajeOpcion.DEFAULT_OPTION,mensajeOpcion.PLAIN_MESSAGE,null,RESULTADO_FINAL,null);
break;
case 2:
resultado = mensajeOpcion.showOptionDialog(this,"¡Perdiste!\nTu record es de: " + controlador.getRecord() + "\nTu puntaje es de: " + controlador.getPuntaje(),"2048",mensajeOpcion.DEFAULT_OPTION,mensajeOpcion.PLAIN_MESSAGE,null,RESULTADO_FINAL,null);
break;
}
return resultado;
}
}

Answer

Note that the underlying container used by JFrames, use BorderLayout by default. Here is a simple example that will add 2 Containers to a JFrame and switches between the containers at the click of a button:

class Interfaz extends JFrame {
    private Container contenedorJuego, contenedorMenu, mainPane;
    private JButton showC;

    public Interfaz() {
        super("MEGA 2048");
        showC = new JButton("Switch);
        contenedorJuego = new JPanel();
        contenedorMenu = new JPanel();
        mainPane = new JPanel(new CardLayout());
    }

    private void initComponents() {
        contenedorJuego.setBorder(BorderFactory
            .createTitledBorder(BorderFactory
            .createRaisedBevelBorder(), "ContenedorJuego"));
        mainPane.add(contenedorJuego, "first");

        contenedorMenu.setBorder(BorderFactory
            .createTitledBorder(BorderFactory
            .createRaisedBevelBorder(), "ContenedorMenu"));
        mainPane.add(contenedorMenu, "second");
        add(mainPane, BorderLayout.CENTER);
        add(showC, BorderLayout.SOUTH);
        addC.addActionListener(new ActionListener() {
            private String selectedComponent = "first";
            @Override
            public void actionPerformed(ActionEvent e) {
                CardLayout cl = (CardLayout)mainPane.getLayout();
                if (selectedComponent.equals("first")) {
                    selectedComponent = "second";
                }
                else {
                    selectedComponent = "first";
                }
                cl.show(mainPane, selectedComponent);
           }
       });      
    }

    public static void main(String []args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                Interfaz f = new Interfaz();
                f.initComponents();
                f.setLocationRelativeTo(null);
                f.setSize(100, 100);
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setVisible(true);
            }
        });
    }
}

I have written this without an IDE but I'm sure it should have all the functions working. The simple idea is to use CardLayout to switch from one container (JPanel) to the other at the click of a button. You don't have to set these components to be visible but you do have to make the JFrame visible and the layout manager will do the rest.

Hope that helps