Author Topic: Java Panel/Frame has different sizes  (Read 7189 times)

0 Members and 1 Guest are viewing this topic.

Offline Munchor

  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 6199
  • Rating: +295/-121
  • Code Recycler
    • View Profile
Java Panel/Frame has different sizes
« on: September 13, 2011, 12:05:17 pm »
I have this code:

Code: [Select]
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Game extends JPanel implements KeyListener {
  /* Game Panel class containing all functions */

  JFrame mainFrame = new JFrame("Game");
  boolean needs_repaint;

  public void paintComponent(Graphics g) {
    /* Draws the elements on the screen */
    super.paintComponent(g);

    System.out.printf("Panel Width: %d\n", this.getWidth());
    System.out.printf("Frame Width: %d\n", this.getParent().getWidth());

    /* Repainting has finished */
    needs_repaint = false;
  }

  public void update() {
    /* Main game loop */
   
    /* Always repaint */
    //this.repaint();
  }

  public void run() {
    /* Displays the frame, start the game */
    mainFrame.setVisible(true);
    this.requestFocus();
  }

  public Game() {
    /* Defines the frame and the game panel */
    this.setFocusable(true);
    this.addKeyListener(this);

    /* Fixed Layout frame */
    mainFrame.setSize(852, 600);
    mainFrame.setResizable(false);
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mainFrame.getContentPane().add(this);   // Add game panel to main frame

    /* Start timer with main game loop */
    Timer timer = new Timer(25, new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        update();
      }});
    timer.start();
  }

  /* Game Class is not abstract, and these functions are not needed */
  public void keyPressed(KeyEvent key) {}
  public void keyReleased(KeyEvent arg0) {}
  public void keyTyped(KeyEvent arg0) {}
 
  public static void main(String[] args) {
    new Game().run();
  }
}

Basically, what happens is that the frame and the panel not always have the same width. This happens in my game Falling Blocks and with the above code as well. Below is what happened when I ran the program several times (it's a bit random, sometimes it has 850, other times it has not).

I have no idea of how to fix this, since my code supposedly gives the frame a fixed size of 852.

Quote
david@davidbuntu:~/temp$ java Game
Panel Width: 850
Frame Width: 850
Panel Width: 850
Frame Width: 850
Panel Width: 842
Frame Width: 842
Panel Width: 850
Frame Width: 850
david@davidbuntu:~/temp$ java Game
Panel Width: 850
Frame Width: 850
Panel Width: 850
Frame Width: 850
david@davidbuntu:~/temp$ java Game
Panel Width: 850
Frame Width: 850
Panel Width: 850
Frame Width: 850
david@davidbuntu:~/temp$ java Game
Panel Width: 836
Frame Width: 836
Panel Width: 842
Frame Width: 842
Panel Width: 836
Frame Width: 836
david@davidbuntu:~/temp$

EDIT: As you can see I also set mainFrame to not resizable, so I'm not resizing it.
« Last Edit: September 13, 2011, 02:05:01 pm by ephan »

Offline nemo

  • LV9 Veteran (Next: 1337)
  • *********
  • Posts: 1203
  • Rating: +95/-11
    • View Profile
Re: Java Panel/Frame has different sizes
« Reply #1 on: September 13, 2011, 07:54:07 pm »
do a System.out.println(getParent()); and System.out.println(mainFrame); and copy/paste the output


Offline JL235

  • LV3 Member (Next: 100)
  • ***
  • Posts: 57
  • Rating: +13/-0
    • View Profile
    • Play My Code
Re: Java Panel/Frame has different sizes
« Reply #2 on: September 13, 2011, 08:31:10 pm »
I believe the issue is that setting the size only sets the current size; what it is right now. It does not set the size you want it to be, after various calls have been made. Disabling resizing is for preventing the user from resizing the component, it doesn't turn resizing off.

In my own code I do:
Code: [Select]
        Dimension size = new Dimension(width, height);
        setSize(size);
        setMinimumSize(size);
        setMaximumSize(size);
        setPreferredSize(size);

You should also probably call 'pack' on the frame, after setting the size and before you make it visible.
Build games in the browser at PlayMyCode.com, @playmycode

Offline Munchor

  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 6199
  • Rating: +295/-121
  • Code Recycler
    • View Profile
Re: Java Panel/Frame has different sizes
« Reply #3 on: September 14, 2011, 07:31:04 am »
I tried your code JL235, but it still doesn't work. Here's MainFrame.java:

Code: [Select]
import java.awt.Dimension;

import javax.swing.JFrame;

@SuppressWarnings("serial")
public class MainFrame extends JFrame {

  public MainFrame(String string) {
     this.setTitle(string);
     Dimension size = new Dimension(850, 600);
     this.setSize(size);
     this.setMinimumSize(size);
     this.setMaximumSize(size);
     this.setPreferredSize(size);
     this.setResizable(false);
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }

  public void run() {
    this.setVisible(true);
  }
}

Thanks :)

@nemo
System.out.println(getParent());
System.out.println(mainFrame);

Where? ;)
« Last Edit: September 14, 2011, 07:47:17 am by ephan »

Offline JL235

  • LV3 Member (Next: 100)
  • ***
  • Posts: 57
  • Rating: +13/-0
    • View Profile
    • Play My Code
Re: Java Panel/Frame has different sizes
« Reply #4 on: September 14, 2011, 10:29:39 pm »
I have added the code I suggested, but for the JPanel, to your original code, and it works fine for me.
Code: [Select]
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class MainFrame extends JPanel implements KeyListener {
  /* Game Panel class containing all functions */

  private JFrame mainFrame;
  private boolean needs_repaint;

  public void paintComponent(Graphics g) {
    /* Draws the elements on the screen */
    super.paintComponent(g);

    System.out.printf("Panel Width: %d\n", this.getWidth());
    System.out.printf("Frame Width: %d\n", this.getParent().getWidth());

    /* Repainting has finished */
    needs_repaint = false;
  }

  public void update() {
    /* Main game loop */
    
    /* Always repaint */
    //this.repaint();
  }

  public void run() {
    /* Displays the frame, start the game */
    mainFrame.setVisible(true);
    this.requestFocus();
  }

  public MainFrame() {
    /* Defines the frame and the game panel */
    this.setFocusable(true);
    this.addKeyListener(this);

    /* Fixed Layout frame */
    Dimension size = new Dimension(850, 600);
    this.setSize(size);
    
    mainFrame = new JFrame("Game");
    mainFrame.setResizable(false);
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mainFrame.getContentPane().add(this);   // Add game panel to main frame
    mainFrame.pack();

    /* Start timer with main game loop */
    Timer timer = new Timer(25, new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        update();
      }});
    timer.start();
  }

  /* Game Class is not abstract, and these functions are not needed */
  public void keyPressed(KeyEvent key) {}
  public void keyReleased(KeyEvent arg0) {}
  public void keyTyped(KeyEvent arg0) {}
  
  public static void main(String[] args) {
    new MainFrame().run();
  }
}

I had a similar problem to this when I wrote my own graphics engine, but it was around 5 years ago, so the solution is pretty hazy. If I remember correctly, it could be that the width is including other items in the JFrame, such as the surrounding border. However I don't know for sure. For safety I'd concentrate on checking the size of your inner JPanel, as this is the component where the size really matters, and not care what the outer frame is using.

I also added a call to pack, to ensure it's all packed down to the size you want.
« Last Edit: September 14, 2011, 10:30:34 pm by JL235 »
Build games in the browser at PlayMyCode.com, @playmycode

Offline Munchor

  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 6199
  • Rating: +295/-121
  • Code Recycler
    • View Profile
Re: Java Panel/Frame has different sizes
« Reply #5 on: September 15, 2011, 09:40:16 am »
I have several files on my code, so asking for help is a bit complicated.

So I made this pastebin to get help. It has all the 4 files, don't worry, it's not a uber-project yet.

I tried packing the frame and constraining the size of the panel AND the frame, but I still get a different size now and then.

It's like:
Correct Size
Correct Size
Correct Size
Wrong Size
Correct Size
Correct Size
Wrong Size

Offline Munchor

  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 6199
  • Rating: +295/-121
  • Code Recycler
    • View Profile
Re: Java Panel/Frame has different sizes
« Reply #6 on: September 20, 2011, 02:36:57 pm »
Bump?

Offline JL235

  • LV3 Member (Next: 100)
  • ***
  • Posts: 57
  • Rating: +13/-0
    • View Profile
    • Play My Code
Re: Java Panel/Frame has different sizes
« Reply #7 on: September 20, 2011, 07:11:12 pm »
Remove the setSize code from the MainFrame; so you don't set any size there. This is what is causing the issue, because the size includes the Window borders. The size of the frame is pretty much irrelevant, it's the size of the inner panel that matters (as this is where you are drawing to). The call to 'pack' ensures the size is as small as possible, whilst the size set on the inner pane prevents the MainFrame being too small (less then 850 by 600). You'll also need to move call to 'pack' into the 'run' method.

The code for MainFrame becomes:
Code: [Select]
import javax.swing.JFrame;

@SuppressWarnings("serial")
public class MainFrame extends JFrame {

  public MainFrame(String string) {
     setTitle(string);
    
     setResizable(false);
    
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }

  public void run() {
    this.pack();
    this.setVisible(true);
  }
}

This fixes it for me.
« Last Edit: September 20, 2011, 07:11:39 pm by JL235 »
Build games in the browser at PlayMyCode.com, @playmycode

Offline Munchor

  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 6199
  • Rating: +295/-121
  • Code Recycler
    • View Profile
Re: Java Panel/Frame has different sizes
« Reply #8 on: October 02, 2011, 12:31:08 pm »
Well, the problem is if I don't set the size on the frame, then the panel won't be 800*600, right?

Here's an example, the frame appears very tiny when displayed.

Offline Binder News

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 785
  • Rating: +46/-3
  • Zombie of Tomorrow
    • View Profile
Re: Java Panel/Frame has different sizes
« Reply #9 on: November 05, 2011, 10:20:17 pm »
@ephan, do you still need help with this?
Spoiler For userbars:







Hacker-in-training!   Z80 Assembly Programmer     Axe Programmer
C++ H4X0R             Java Coder                           I <3 Python!

Perdidisti ludum     Cerebrum non habes

"We are humans first, no matter what."
"Fame is a vapor, popularity an accident, and riches take wings. Only one thing endures, and that is character."
Spoiler For Test Results: