Reputation: 313
For some reason, the JFrame is too small when run, and using pack();
doesn't seem to fix the problem. Any ideas?
public class Window {
public Window(String title, Game game) {
// Creates new JFrame
JFrame frame = new JFrame(title);
// Adds Game to window
frame.add(game);
frame.pack();
// Settings of Window
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
The cyan background is supposed to be a 64 x 64 border in the bottom and right sides. The boxes drawn are correct, which I checked by resizing the window. However the window is too small and does not fit the canvas.
Game Class:
public class Game extends Canvas implements Runnable {
private Handler handler;
public Game() {
// Create new window
Window window = new Window("Horses Aren't Real", this);
handler = new Handler();
this.addKeyListener(new KeyInput(handler));
handler.addObject(new Daanish(100, 100, ID.Player, handler));
}
public static void main (String args[]) {
// Creates new game
new Game();
}
public void draw() {
// Creates a new BufferStrategy
BufferStrategy bs = this.getBufferStrategy();
if (bs == null) {
// This allows the game to preload 3 frames in order to prevent choppy framrate
this.createBufferStrategy(3);
return;
}
// Create Graphics
Graphics g = bs.getDrawGraphics();
g.setColor(Color.cyan);
g.fillRect(0, 0, 1024, 640);
g.setColor(Color.black);
g.fillRect(0, 0, 960, 576);
handler.draw(g);
// Remove frame from queue
g.dispose();
bs.show();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(1024, 640);
}
}
Upvotes: 0
Views: 1851
Reputation: 347314
So you're running into a number of issues. The first been, the size of the window must also account for the frame decorations, this means that the available space for the content is the size of the window MINUS the size of the frame decorations.
Setting the size of the window directly is ill-advised.
pack
asks the content of the frame for it's preferred size and uses that to wrap the window around it. So, instead of window size - decorations = content size
, you have content size + decorations = window size
From the JavaDocs
Causes this Window to be sized to fit the preferred size and layouts of its subcomponents. The resulting width and height of the window are automatically enlarged if either of dimensions is less than the minimum size as specified by the previous call to the setMinimumSize method.
So, instead, override preferredSize
of the Game
class and return the amount of space you want, may be something like...
public class Game extends JPanel {
//...
@Override
public Dimension getPreferredSize() {
return new Dimension(800, 600);
}
//...
}
Your next problem is, Window
extends from JFrame
, but in the constructor, you're creating ANOTHER Frame
... so which one is actually doing what?
Remove the confusion. Avoid extending from top level containers like JFrame
, you're not adding any new functionality to it
public class Window {
public Window(String title, Game game) {
// Creates new JFrame
JFrame frame = new JFrame(title);
// Adds Game to window
frame.add(game);
frame.pack();
// Settings of Window
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
So, I took your "updated" code, modified it so it would run, ran and didn't have any issues...
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Game game = new Game();
Window window = new Window("Help", game);
game.start();
}
});
}
public class Window {
public Window(String title, Game game) {
// Creates new JFrame
JFrame frame = new JFrame(title);
// Adds Game to window
frame.add(game);
frame.setResizable(false);
frame.pack();
// Settings of Window
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
public class Game extends Canvas { //implements Runnable {
// private Handler handler;
public Game() {
//
// handler = new Handler();
// this.addKeyListener(new KeyInput(handler));
//
// handler.addObject(new Daanish(100, 100, ID.Player, handler));
}
public void start() {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
draw();
try {
Thread.sleep(40);
} catch (InterruptedException ex) {
}
}
}
});
thread.start();
}
public void draw() {
// Creates a new BufferStrategy
BufferStrategy bs = this.getBufferStrategy();
if (bs == null) {
// This allows the game to preload 3 frames in order to prevent choppy framrate
this.createBufferStrategy(3);
return;
}
// Create Graphics
Graphics g = bs.getDrawGraphics();
g.setColor(Color.cyan);
g.fillRect(0, 0, 1024, 640);
g.setColor(Color.black);
g.fillRect(0, 0, 960, 576);
// handler.draw(g);
// Remove frame from queue
g.dispose();
bs.show();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(1024, 640);
}
}
}
However, I'm running on MacOS. There is a little known issue with setResizable
I've run across on Windows, where the window decorations change size when setResizable
is called.
The "basic" solution is to call setResziable
BEFORE calling pack
, so that the frame decorations are modified before the the API makes decisions about how to update the size of the window.
I had thought this was fixed in later (8+) versions of Java, but since I don't run Windows, it's impossible for me to test
See My JFrame always becomes a few pixels too big. for some more details.
Upvotes: 2
Reputation: 100
public class Window extends JFrame {
public Window(final int width, final int height, String title, Game game) {
super(title);
// Set dimensions
Dimension d = new Dimension(width, height);
game.setPreferredSize(d);
// Adds Game to window
add(game);
// Settings of Window
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
pack();
setVisible(true);
}
}
When you use pack, the frame generaly resize to content size
Upvotes: 1