Omnimaga

General Discussion => Technology and Development => Computer Programming => Topic started by: Munchor on September 13, 2011, 12:05:17 pm

Title: Java Panel/Frame has different sizes
Post by: Munchor 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.
Title: Re: Java Panel/Frame has different sizes
Post by: nemo on September 13, 2011, 07:54:07 pm
do a System.out.println(getParent()); and System.out.println(mainFrame); and copy/paste the output
Title: Re: Java Panel/Frame has different sizes
Post by: JL235 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.
Title: Re: Java Panel/Frame has different sizes
Post by: Munchor 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? ;)
Title: Re: Java Panel/Frame has different sizes
Post by: JL235 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.
Title: Re: Java Panel/Frame has different sizes
Post by: Munchor 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 (https://gist.github.com/73ee38624eeedb9e1611) 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
Title: Re: Java Panel/Frame has different sizes
Post by: Munchor on September 20, 2011, 02:36:57 pm
Bump?
Title: Re: Java Panel/Frame has different sizes
Post by: JL235 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.
Title: Re: Java Panel/Frame has different sizes
Post by: Munchor 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 (https://gist.github.com/5fa4a007d265dc0ac750), the frame appears very tiny when displayed.
Title: Re: Java Panel/Frame has different sizes
Post by: Binder News on November 05, 2011, 10:20:17 pm
@ephan, do you still need help with this?