Peter
Peter

Reputation: 145

My GUI won't show and I can't seem to understand why?

I am writing a video game GUI and I want to firstly open a frame with a menu bar and when the user clicks on play in the menu a JPanel that is in a different class gets added to the current one and it ends up with a frame containing the menu bar and the JPanel. When I run the code bellow I don't get any errors and the console initiates the process. The problem is nothing shows on the screen?? Not the initial frame or anything else.

The code for the frame that calls the class with the JPanel is:

/*-----------------------------------------------------------------------------------------------------*/

package Testes;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


import javax.swing.*;


public class Tetris extends JFrame{


    private static final long serialVersionUID = 1L;
    public static final int WIDTH = 250;
    public static final int HEIGHT = 490;


    public Tetris() {

        JFrame frame = new JFrame();
        TetrisBoard janela = new TetrisBoard();


        JMenuBar menubar = new JMenuBar();

        JMenu start = new JMenu("Start");


        JMenuItem play = new JMenuItem("Play");
        play.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e) 
            {

                janela.startGame();
            }
        });
        start.add(play);

        JMenuItem exit = new JMenuItem("Exit");
        exit.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e) 
            {
                System.exit(0);
            }
        });
        start.add(exit);

        JMenu help = new JMenu("Help");

        JMenuItem manual = new JMenuItem("User Manual");
        manual.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e) 
            {
                JOptionPane.showMessageDialog(null, "The goal of Tetris is to eliminate \nas many lines as possible before\n the Tetrominoes reach the top.\nControls:\n\u2190        - Move Left\n\u2192        - Move Right\n\u2193         - Drop\n" +
                        "C        - Rotate AntiClockwise\nV        - Rotate Clockwise\nP        - Pause\nEsc    - Quit","Instructions", JOptionPane.OK_OPTION, new ImageIcon());
            }
        });
        help.add(manual);


        JMenuItem about = new JMenuItem("About");
        about.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e) 
            {
                JLabel label = new JLabel("<html><center>Tetris made by GG<br>MEEC<br>2020<html>");
                label.setHorizontalAlignment(SwingConstants.CENTER);
                JOptionPane.showMessageDialog(null, label, "About", JOptionPane.INFORMATION_MESSAGE);
            }
        });
        help.add(about);


        menubar.add(start);
        menubar.add(help);


        frame.add(janela,BorderLayout.CENTER);
        frame.add(menubar,BorderLayout.NORTH); 
        janela.setFocusable(true);
        frame.setTitle("Tetris");
        frame.setLayout(new BorderLayout());
        frame.setSize(250, 490);
        //setPreferredSize(new Dimension(255, 495));
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        frame.pack();






        }


    public static void main(String[] args) {


        new Tetris();


    }

}
/*-----------------------------------------------------------------------------------------------------*/

And the class with the JPanel is:

/*-----------------------------------------------------------------------------------------------------*/
package Testes;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;


public class TetrisBoard extends JPanel implements KeyListener/*, ActionListener*/{

    private static final long serialVersionUID = 1L;

    public static final int COLOR_MIN = 35;

    public static final int COLOR_MAX = 255 - COLOR_MIN;

    public static final int BORDER_WIDTH = 5;

    public static final int COL_COUNT = 10;

    public static final int VISIBLE_ROW_COUNT = 20;

    public static final int HIDDEN_ROW_COUNT = 2;

    public static final int ROW_COUNT = VISIBLE_ROW_COUNT + HIDDEN_ROW_COUNT;

    public static final int TILE_SIZE = 24;

    public static final int SHADE_WIDTH = 4;

    private static final int CENTER_X = COL_COUNT * TILE_SIZE / 2;

    public static final int CENTER_Y = VISIBLE_ROW_COUNT * TILE_SIZE / 2;

    public static final int PANEL_WIDTH = COL_COUNT * TILE_SIZE + BORDER_WIDTH * 2;

    public static final int PANEL_HEIGHT = VISIBLE_ROW_COUNT * TILE_SIZE + BORDER_WIDTH * 2;

    public static final Font LARGE_FONT = new Font("Tahoma", Font.BOLD, 16);

    public static final Font SMALL_FONT = new Font("Tahoma", Font.BOLD, 12);

    public static final long FRAME_TIME = 20L;

    public static final int TYPE_COUNT = TileType.values().length;

    public boolean isPaused;

    public boolean isNewGame;

    public boolean isGameOver;

    public int level;

    public int score;

    public Random random;

    public Clock logicTimer;

    public TileType currentType;

    public TileType nextType;

    public int currentCol;

    private int currentRow;

    public int currentRotation;

    public int dropCooldown;

    public float gameSpeed;

    public String difficulty = "Easy"; 

    public int newLevel;

    public int lines;

    public int cleared;

    public TileType[][] tiles;


    public TetrisBoard() {

        addKeyListener(this);

        this.tiles = new TileType[ROW_COUNT][COL_COUNT];

        setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
        setBackground(Color.BLACK);

        startGame();
    }

    public void clear() {

        for(int i = 0; i < ROW_COUNT; i++) {
            for(int j = 0; j < COL_COUNT; j++) {
                tiles[i][j] = null;
            }
        }
    }

    public boolean isValidAndEmpty(TileType type, int x, int y, int rotation) {

        if(x < -type.getLeftInset(rotation) || x + type.getDimension() - type.getRightInset(rotation) >= COL_COUNT) {
            return false;
        }

        if(y < -type.getTopInset(rotation) || y + type.getDimension() - type.getBottomInset(rotation) >= ROW_COUNT) {
            return false;
        }

        for(int col = 0; col < type.getDimension(); col++) {
            for(int row = 0; row < type.getDimension(); row++) {
                if(type.isTile(col, row, rotation) && isOccupied(x + col, y + row)) {
                    return false;
                }
            }
        }
        return true;
    }

    public void addPiece(TileType type, int x, int y, int rotation) {

        for(int col = 0; col < type.getDimension(); col++) {
            for(int row = 0; row < type.getDimension(); row++) {
                if(type.isTile(col, row, rotation)) {
                    setTile(col + x, row + y, type);
                }
            }
        }
    }


    public int checkLines() {
        int completedLines = 0;

        for(int row = 0; row < ROW_COUNT; row++) {
            if(checkLine(row)) {
                completedLines++;
            }
        }
        return completedLines;
    }


    public boolean checkLine(int line) {

        for(int col = 0; col < COL_COUNT; col++) {
            if(!isOccupied(col, line)) {
                return false;
            }
        }

        for(int row = line - 1; row >= 0; row--) {
            for(int col = 0; col < COL_COUNT; col++) {
                setTile(col, row + 1, getTile(col, row));
            }
        }
        return true;
    }


    public boolean isOccupied(int x, int y) {
        return tiles[y][x] != null;
    }

    public void setTile(int  x, int y, TileType type) {
        tiles[y][x] = type;
    }


    public TileType getTile(int x, int y) {
        return tiles[y][x];
    }

    //@Override
    public void paintComponent(Graphics g) {
        this.paintComponent(g);


        g.translate(BORDER_WIDTH, BORDER_WIDTH);

        if(isPaused()) {

            g.setFont(LARGE_FONT);
            g.setColor(Color.GREEN);    
            String msg = "PAUSED";
            g.drawString(msg, CENTER_X - g.getFontMetrics().stringWidth(msg) / 2, CENTER_Y);

        } else if(isNewGame() || isGameOver()) {

            g.setFont(LARGE_FONT);
            g.setColor(Color.WHITE);            

            g.setColor(Color.GREEN);
            String msg = isNewGame() ? "TETRIS" : "GAME OVER";
            g.drawString(msg, CENTER_X - g.getFontMetrics().stringWidth(msg) / 2, 150);
            g.setFont(SMALL_FONT);                      
            msg = "Press Enter to Play" + (isNewGame() ? "" : " Again");
            g.drawString(msg, CENTER_X - g.getFontMetrics().stringWidth(msg) / 2, 300);

        } else {

            for(int x = 0; x < COL_COUNT; x++) {
                for(int y = HIDDEN_ROW_COUNT; y < ROW_COUNT; y++) {
                    TileType tile = getTile(x, y);
                    if(tile != null) {
                        drawTile(tile, x * TILE_SIZE, (y - HIDDEN_ROW_COUNT) * TILE_SIZE, g);
                    }
                }
            }


            TileType type = getPieceType();
            int pieceCol = getPieceCol();
            int pieceRow = getPieceRow();
            int rotation = getPieceRotation();

            for(int col = 0; col < type.getDimension(); col++) {
                for(int row = 0; row < type.getDimension(); row++) {
                    if(pieceRow + row >= 2 && type.isTile(col, row, rotation)) {
                        drawTile(type, (pieceCol + col) * TILE_SIZE, (pieceRow + row - HIDDEN_ROW_COUNT) * TILE_SIZE, g);
                    }
                }
            }

            g.setColor(Color.DARK_GRAY);
            for(int x = 0; x < COL_COUNT; x++) {
                for(int y = 0; y < VISIBLE_ROW_COUNT; y++) {
                    g.drawLine(0, y * TILE_SIZE, COL_COUNT * TILE_SIZE, y * TILE_SIZE);
                    g.drawLine(x * TILE_SIZE, 0, x * TILE_SIZE, VISIBLE_ROW_COUNT * TILE_SIZE);
                }
            }

        }

        g.setColor(Color.GREEN);    
        g.drawRect(0, 0, TILE_SIZE * COL_COUNT, TILE_SIZE * VISIBLE_ROW_COUNT);
    }

    public void drawTile(TileType type, int x, int y, Graphics g) {
        drawTile(type.getBaseColor(), type.getLightColor(), type.getDarkColor(), x, y, g);
    }

    public void drawTile(Color base, Color light, Color dark, int x, int y, Graphics g) {

        g.setColor(base);
        g.fillRect(x, y, TILE_SIZE, TILE_SIZE);

        g.setColor(dark);
        g.fillRect(x, y + TILE_SIZE - SHADE_WIDTH, TILE_SIZE, SHADE_WIDTH);
        g.fillRect(x + TILE_SIZE - SHADE_WIDTH, y, SHADE_WIDTH, TILE_SIZE);

        g.setColor(light);
        for(int i = 0; i < SHADE_WIDTH; i++) {
            g.drawLine(x, y + i, x + TILE_SIZE - i - 1, y + i);
            g.drawLine(x + i, y, x + i, y + TILE_SIZE - i - 1);

        }
    }


    public void startGame() {

        this.random = new Random();
        this.isNewGame = true;

        if(this.difficulty.equals("Easy")) {
            this.gameSpeed=1.0f;
        }else if(this.difficulty.equals("Intermediate")) {
            this.gameSpeed=3.0f;
        }else if(this.difficulty.equals("Hard")) {
            this.gameSpeed=6.0f;
        }

        this.level=1;
        this.cleared=0;
        this.newLevel=0;

        this.logicTimer = new Clock(gameSpeed);
        logicTimer.setPaused(true);


        while(true) {
            long start = System.nanoTime();
            logicTimer.update();

            if(logicTimer.hasElapsedCycle()) {
                updateGame();
            }

            //Decrement the drop cool down if necessary.
            if(dropCooldown > 0) {
                dropCooldown--;
            }


            renderGame();

            long delta = (System.nanoTime() - start) / 1000000L; // delta in miliseconds
            if(delta < FRAME_TIME) {
                try {
                    Thread.sleep(FRAME_TIME - delta);   // sleeps the difference between the fps and the time for the game to process (delta)
                } catch(Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }


    public void updateGame() {


        if(isValidAndEmpty(currentType, currentCol, currentRow + 1, currentRotation)) {
            currentRow++;
        } else {

            addPiece(currentType, currentCol, currentRow, currentRotation);

            cleared = checkLines();
            if(cleared > 0) {
                lines += cleared;
                score += 50 << cleared; // left bit shift - add the number of zeros on the right to the binary version of the number on the right
                // score = score + 50 << cleared;

            }

            //newLevel+=cleared;
            gameSpeed += 0.035f;
            logicTimer.setCyclesPerSecond(gameSpeed);
            logicTimer.reset();

            dropCooldown = 25;



            if(newLevel<10) {
                newLevel+=cleared;
            }else if(newLevel>=10) {
                level+=1;
                newLevel=0;
                cleared=0;
            }

            spawnPiece();
        }       
    }

    public void renderGame() {
        repaint();

    }

    public void resetGame() {
        this.level = 1;
        this.score = 0; 
        this.lines = 0;
        this.newLevel = 0;
        this.cleared = 0;



        if(this.difficulty.equals("Easy")) {
            this.gameSpeed=1.0f;
        }else if(this.difficulty.equals("Intermediate")) {
            this.gameSpeed=3.0f;
        }else if(this.difficulty.equals("Hard")) {
            this.gameSpeed=6.0f;
        }


        this.nextType = TileType.values()[random.nextInt(TYPE_COUNT)];
        this.isNewGame = false;
        this.isGameOver = false;        
        clear();


        logicTimer.reset();
        logicTimer.setCyclesPerSecond(gameSpeed);   

        spawnPiece();
    }


    public void spawnPiece() {

        this.currentType = nextType;
        this.currentCol = currentType.getSpawnColumn();
        this.currentRow = currentType.getSpawnRow();
        this.currentRotation = 0;
        this.nextType = TileType.values()[random.nextInt(TYPE_COUNT)];

        if(!isValidAndEmpty(currentType, currentCol, currentRow, currentRotation)) {
            lose(); 
        }       
    }

    public void lose() 
    {

        this.isGameOver = true;
        logicTimer.setPaused(isPaused);

        String info = "";


        if (score>HighScore.getHighScores()[9].getScore())
        {

            info="You got a high score!\n<br>Please enter you name.\n<br>(Note: Only 10 characters will be saved)";
            JLabel label = new JLabel("<html><center>GAME OVER\n<br>" + info);
            label.setHorizontalAlignment(SwingConstants.CENTER);

            String name=JOptionPane.showInputDialog(null, label,"Tetris", JOptionPane.INFORMATION_MESSAGE);
            if (name!=null) {
                HighScore.addHighScore(new HighScore(score,level,lines,(name.length()>10)?name.substring(0, 10):name,(difficulty.length()>12)?difficulty.substring(0, 12):difficulty));
            }
        }else {


            info="You didn't get a high score:( \n<br>Keep trying you will get it next time!";
            JLabel label = new JLabel("<html><center>GAME OVER\n<br>" + info);
            label.setHorizontalAlignment(SwingConstants.CENTER);


            JOptionPane.showMessageDialog(null, label, "Tetris", JOptionPane.PLAIN_MESSAGE);
        }


        if (JOptionPane.showConfirmDialog(null, "Do you want to play again?",
                "Tetris", JOptionPane.YES_NO_OPTION)==JOptionPane.YES_OPTION) {
            this.score=0;
            this.level=0;
            this.lines=0;


            startGame();
        }else
        {
            //If not, quit
            System.exit(0);
        }
    }


    public void rotatePiece(int newRotation) {

        int newColumn = currentCol;
        int newRow = currentRow;


        int left = currentType.getLeftInset(newRotation);
        int right = currentType.getRightInset(newRotation);
        int top = currentType.getTopInset(newRotation);
        int bottom = currentType.getBottomInset(newRotation);


        if(currentCol < -left) {
            newColumn -= currentCol - left;
        } else if(currentCol + currentType.getDimension() - right >= COL_COUNT) {
            newColumn -= (currentCol + currentType.getDimension() - right) - COL_COUNT + 1;
        }


        if(currentRow < -top) {
            newRow -= currentRow - top;
        } else if(currentRow + currentType.getDimension() - bottom >= ROW_COUNT) {
            newRow -= (currentRow + currentType.getDimension() - bottom) - ROW_COUNT + 1;
        }


        if(isValidAndEmpty(currentType, newColumn, newRow, newRotation)) {
            currentRotation = newRotation;
            currentRow = newRow;
            currentCol = newColumn;
        }


    }

    public boolean isPaused() {
        return isPaused;
    }

    public boolean isGameOver() {
        return isGameOver;
    }

    public boolean isNewGame() {
        return isNewGame;
    }

    public int getScore() {
        return score;
    }

    public int getLevel() {
        return level;
    }

    public String getDiff(){
        return difficulty;
    }

    public int getLines() {
        return lines;
    }


    public TileType getPieceType() {
        return currentType;
    }

    public TileType getNextPieceType() {
        return nextType;
    }

    public int getPieceCol() {
        return currentCol;
    }

    public int getPieceRow() {
        return currentRow;
    }

    public int getPieceRotation() {
        return currentRotation;
    }


    //@Override
        public void keyPressed(KeyEvent e) {

            switch(e.getKeyCode()) {

            case KeyEvent.VK_DOWN:
                if(!isPaused && dropCooldown == 0) {
                    logicTimer.setCyclesPerSecond(25.0f);
                }
                break;

            case KeyEvent.VK_LEFT:
                if(!isPaused && isValidAndEmpty(currentType, currentCol - 1, currentRow, currentRotation)) {
                    currentCol--;
                }
                break;

            case KeyEvent.VK_RIGHT:
                if(!isPaused && isValidAndEmpty(currentType, currentCol + 1, currentRow, currentRotation)) {
                    currentCol++;
                }
                break;

            case KeyEvent.VK_C:
                if(!isPaused) {
                    rotatePiece((currentRotation == 0) ? 3 : currentRotation - 1);
                }           
                break;

            case KeyEvent.VK_V:
                if(!isPaused) {
                    rotatePiece((currentRotation == 3) ? 0 : currentRotation + 1);

                }
                break;  

            case KeyEvent.VK_P:
                if(!isGameOver && !isNewGame) {
                    isPaused = !isPaused;
                    logicTimer.setPaused(isPaused);

                }
                break;

            case KeyEvent.VK_ENTER:
                if(isGameOver || isNewGame) {
                    resetGame();
                }
                break;


            case KeyEvent.VK_ESCAPE:

                int ans = JOptionPane.showConfirmDialog(null, "Are you sure you want to quit?\n", "Tetris", JOptionPane.INFORMATION_MESSAGE);
                    if(ans==1 || ans==2) {
                        //isPaused = !isPaused;
                        //logicTimer.setPaused(isPaused);
                        return;
                    }else if(ans==0) {
                        System.exit(0);                     
                    }                   

                }


            }
        }


    //@Override
        public void keyReleased(KeyEvent e) {

            switch(e.getKeyCode()) {

            case KeyEvent.VK_S:
                logicTimer.setCyclesPerSecond(gameSpeed);
                logicTimer.reset();
                break;
            }

        }



    @Override
    public void keyTyped(KeyEvent e) {}


}

Upvotes: 1

Views: 76

Answers (2)

Andrew Thompson
Andrew Thompson

Reputation: 168815

This works:

enter image description here

You might notice it replaces the ridiculously long & complicated TetrisBoard with a red panel with a preferred size of 400 x 200. This is how you should figure such things out. Post a minimal reproducible example in future.

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

public class Tetris extends JFrame {

    public Tetris() {

        JFrame frame = new JFrame();
        JPanel janela = new JPanel();
        janela.setBackground(Color.RED);
        janela.setPreferredSize(new Dimension(400,200));

        JMenuBar menubar = new JMenuBar();
        JMenu start = new JMenu("Start");
        JMenuItem play = new JMenuItem("Play");
        start.add(play);
        JMenuItem exit = new JMenuItem("Exit");
        start.add(exit);
        JMenu help = new JMenu("Help");

        JMenuItem manual = new JMenuItem("User Manual");
        help.add(manual);

        JMenuItem about = new JMenuItem("About");
        help.add(about);

        menubar.add(start);
        menubar.add(help);

        frame.add(janela, BorderLayout.CENTER);
        frame.setJMenuBar(menubar);
        janela.setFocusable(true);
        frame.setTitle("Tetris");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        new Tetris();
    }
}

Upvotes: 1

George Z.
George Z.

Reputation: 6808

First of all, dont add a JMenuBar by frame.add(myJMenuBar,someConstraints). Do it by calling the method frame.setJMenuBar(myJMenuBar);

Secondly, you add the components into the frame (its content pane), and after that you frame.setLayout(new BorderLayout());, while you should first set the layout and AFTER add the components to it:

frame.setLayout(new BorderLayout());
frame.add(janela, BorderLayout.CENTER);

Upvotes: 1

Related Questions