0

I'm making a game in Java and first I didn't use a JPanel which caused flickering on repaint() and so I decided to use it. I'm not sure how to implement it in my current code. When I tried to do so all I got was a window that was as small as it gets. My original Window class code:

public class Window extends JFrame {
private double stepLen;

public Window(double stepLen) {
    this.stepLen = stepLen;

    this.setSize(800, 600);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setResizable(false);
    this.setTitle("Frogger");
    this.setLayout(null);

    getContentPane().setBackground(Color.black);

    Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
    int x = (dim.width - this.getSize().width)/2;
    int y = (dim.height - this.getSize().height)/2;

    this.setLocation(x, y);

    JLabel goal = new JLabel();
    goal.setText("|=========|");
    goal.setForeground(Color.WHITE);
    goal.setFont(new Font("Seif", Font.PLAIN, 20));
    add(goal);
    goal.setBounds(325, -10, 600, 50);

    setFocusable(true);
    requestFocusInWindow();

    this.setVisible(true);
}

This code works and it creates a window. Main class:

Window window = new Window(50);

And then I tried to do it this way: I have separate GameFrame (JFrame) and GameCanvas (JPanel) classes. The Frame looks like this:

public class GameFrame extends JFrame{
private double stepLen;

public GameFrame() {
    this.stepLen = 50;

    this.setSize(800, 600);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setResizable(false);
    this.setTitle("Frogger");
    this.setLayout(null);
    this.setVisible(true);

    this.getContentPane().setBackground(Color.black);

    Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
    int x = (dim.width - this.getSize().width)/2;
    int y = (dim.height - this.getSize().height)/2;

    GameCanvas gcanvas = new GameCanvas();
    this.add(gcanvas);
    this.pack();

    this.setLocation(x, y);

}

}


}

And the GameCanvas class

public class GameCanvas extends JPanel {
public GameCanvas() {
    setDoubleBuffered(true);
    JLabel goal = new JLabel();
    goal.setText("|=========|");
    goal.setForeground(Color.WHITE);
    goal.setFont(new Font("Seif", Font.PLAIN, 20));
    this.add(goal);
    goal.setBounds(325, -10, 600, 50);

    this.getPreferredSize();

    this.setVisible(true);

    this.repaint();
}
T1mpp4
  • 63
  • 8

2 Answers2

2

Camickr is correct - go up vote and mark his answer as correct, this is only here to save him from pulling out what little hair he has remaining

  • You're using a null layout, without taking over its responsibility
  • Failed to provide sizing hints to for the component to allow the layout manager (which you're no longer using) to do it's job

This are all common mistakes, to which there are countless answers already provided

GameFrame

public class GameFrame extends JFrame {

    private double stepLen;

    public GameFrame() {
        this.stepLen = 50;

        this.setSize(800, 600);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setResizable(false);
        this.setTitle("Frogger");
        // Well, there's your problem...
        //this.setLayout(null);
        // Don't do this here...
        this.setVisible(true);

        this.getContentPane().setBackground(Color.black);

        // Simpler way to achieve this
        //Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        //int x = (dim.width - this.getSize().width) / 2;
        //int y = (dim.height - this.getSize().height) / 2;

        GameCanvas gcanvas = new GameCanvas();
        this.add(gcanvas);
        this.pack();

        //this.setLocation(x, y);

        setLocationRelativeTo(null);
        setVisible(true);

    }

}

GameCanvas

public class GameCanvas extends JPanel {

    public GameCanvas() {
        // Pointless
        //setDoubleBuffered(true);
        JLabel goal = new JLabel();
        goal.setText("|=========|");
        goal.setForeground(Color.WHITE);
        goal.setFont(new Font("Seif", Font.PLAIN, 20));
        this.add(goal);
        // Pointless
        //goal.setBounds(325, -10, 600, 50);

        // Pointless
        //this.getPreferredSize();
        // Pointless
        //this.setVisible(true);
        // Pointless
        //this.repaint();
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(400, 400);
    }

    @Override
    public void paintComponent(Graphics g) {

        int firstRoad = 5;
        int i = 0;
        int max = 10;

        Graphics2D g2 = (Graphics2D) g;

        super.paintComponent(g2);
        g2.setColor(Color.WHITE);
        g2.drawRect(5, 30, 75, 40);

        while (i < max) {
            g2.setColor(Color.WHITE);
            g2.setStroke(new BasicStroke(3));

            if (i % 2 == 0) {
                g.setColor(Color.WHITE);
                g.drawRect(3, firstRoad + 50 * i, 793, 50);
                //g.fillRect(3, firstRoad + 50 * i, 793, 50);
            } else {
                g2.setColor(Color.WHITE);
                g2.drawRect(3, firstRoad + 50 * i, 793, 50);
            }
            i++;
        }
    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • @camickr Really, if it's such an issue to you maybe you should stop answering questions which should be marked as duplicates and/or downvoted of existences :P – MadProgrammer Mar 11 '17 at 22:44
  • Most questions are slightly different and it takes time to find the "duplicate" that closely matches all the differences. I attempt to highlight the problems and use the tutorial for the solution. The OP was originally given three suggestions: 1) class names, 2) don't use null layout and 3) override getPreferredSize(). The OP reposted code with new class names but completely ignored the 2nd and 3rd suggestions, indicating they didn't bother to take the time to read the tutorial and download the code. Now the OP will expect to be spoon fed the code for every question. – camickr Mar 12 '17 at 01:27
  • @camickr Done and done – MadProgrammer Mar 12 '17 at 01:44
  • How is that a duplicate? That answer talks about adding the wrong component to the frame. – camickr Mar 12 '17 at 02:47
  • @camickr Since nothing I do will make you happy, I'll leave it to you to re-open and find a suitable duplicate - one of the main reasons I choose it it because it links to one of you blogs describing custom painting approaches - I'd delete the answer, but I can't – MadProgrammer Mar 12 '17 at 03:00
-1

So, the way I was taught in my AP Computer Science class is to set your frame size and other frame characteristics in your main. Here is an example:

import javax.swing.JFrame;

public class theSetupClass{
    public static void main(String[] args){
        JFrame theGUI = new JFrame();

        theGUI.setSize(300,400); //Sets the frame size to 300 by 400
        theGUI.setTitle("Example");
        theGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        theComponentClass component = new theComponentClass(); //Create new theComponentClass
        frame.add(component);//Add theComponentClass to theGUI

        frame.setVisible(true);
    }
}

The code above creates the JFrame and adds the following class to it.

import java.awt.*;
import javax.swing.*;
public class theComponentClass extends JComponent{ 
    public void paintComponent(Graphics g){
        Graphics2D g2 = (Graphics2D) g;

        Rectangle r = new Rectangle(10,10,this.getWidth()-10,this.getHeight()-10); 
        //Creates a rectangle that is 10 pixels away from all sides of the frame
        g2.fill(r); //Draws and fills the rectangle
    }
}

I hope that you find this helpful!

Josh Heaps
  • 335
  • 1
  • 8
  • Wrong approach on two accounts; 1- You don't need to set the size of the frame, lots of reasons,but mostly because the size of the frame needs to include the (variable sized) frame borders, which always makes the contents small; 2- You failed to honour the paint chain which will cause no end of other issues, besides, `paintComponent` never needs to be `public` – MadProgrammer Mar 11 '17 at 20:45