I am trying to build a simple basic to a game for my class in Game Engine Architecture. But my JFrame just wont show anything.
My code is currently structured like this:
Implementation.java (This is some arbitrary implementation of the Engine-package I'm creating)
public class Implementation {
public static void main(String[] args){
World w = new World("Hej", "M:\\workspace\\SP6\\pics\\tulips.jpg",1024,768);
}
}
World.java
public class World extends JFrame{
private static final long serialVersionUID = 1L;
private SpritePanel spritePanel;
private JPanel bottom;
private int width;
private int height;
public World(String windowCaption, String bgPath, int width, int height){
super(windowCaption);
spritePanel = new SpritePanel(bgPath);
add(spritePanel, BorderLayout.CENTER);
System.out.println(spritePanel);
bottom = new JPanel();
bottom.add(new JLabel("Hej"));
add(bottom, BorderLayout.SOUTH);
Dimension size = new Dimension(width,height);
setSize(size);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setVisible(true);
validate();
repaint();
}
SpritePanel.java
public class SpritePanel extends JPanel {
private static final long serialVersionUID = 1L;
private ImageIcon background;
private ArrayList<Sprite> sprites = new ArrayList<Sprite>();
public SpritePanel(String bgPath){
background = new ImageIcon(bgPath);
setLayout(null);
Dimension size = new Dimension(background.getIconWidth(), background.getIconHeight());
setPreferredSize(size);
setMaximumSize(size);
setMinimumSize(size);
}
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(background.getImage(), 0, 0, this);
System.out.println("painted panel");
}
}
So the basic action flow at the moment (from what I can see):
The thing is the paintComponent methods in the JPanel and SpritePanel doesn't seem to get called. As you can see I added a System.out.println in the paintComponent for SpritePanel and that line is never executed.
Another thing I noticed is that the pack seems to know that the components are there. Because if I comment the three lines
spritePanel = new SpritePanel(bgPath);
add(spritePanel, BorderLayout.CENTER);
System.out.println(spritePanel);
The windows size when I run the program is reduced to the size of the "bottom"-JPanel. I can't see the JLabel that I added to the panel but the window size is the size of it. So the pack() method seems to be finding the dimensions of my components.
If I comment the three lines that adds the bottom panel as well the window size is reduced to no height and the width it gets from the standard icons.
I've been trying different things to get it to work but to no avail. I have programmed with Swing before and made working programs but I just can't seem to find the problem here.
Help very much appreciated.
A JFrame is like a Window with border, title, and buttons. We can implement most of the java swing applications using JFrame. By default, a JFrame can be displayed at the top-left position of a screen. We can display the center position of JFrame using the setLocationRelativeTo() method of Window class.
JFrame class is a type of container which inherits the java. awt. Frame class. JFrame works like the main window where components like labels, buttons, textfields are added to create a GUI.
JFrame is a top-level container that provides a window on the screen. A frame is actually a base window on which other components rely, namely the menu bar, panels, labels, text fields, buttons, etc. Almost every other Swing application starts with the JFrame window.
JFrame is a normal window with its normal buttons (optionally) and decorations. JDialog on the other side does not have a maximize and minimize buttons and usually are created with JOptionPane static methods, and are better fit to make them modal (they block other components until they are closed).
Something may be wrong with your with your String path. What you should do though, instead o reading a file, you should be reading a URL, loading from the class path. At time of deployment, you'll find out that the file path won't work, so it's better to package your image as an embedded resource, putting the image in the class path. I had no problems when doing this. Here's what I did.
Change the path to a path relative to my class path
World w = new World("Hej", "/resources/stackoverflow5.png", 1024, 768);
Changed loading from a file to loading from a URL from my class path
background = new ImageIcon(SpritePanel.class.getResource(bgPath));
Put the image in resources
package in my class path
Everything works fine
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Implementation {
public static void main(String[] args) {
World w = new World("Hej", "/resources/stackoverflow5.png", 1024, 768);
}
}
class World extends JFrame {
private static final long serialVersionUID = 1L;
private SpritePanel spritePanel;
private JPanel bottom;
private int width;
private int height;
public World(String windowCaption, String bgPath, int width, int height) {
super(windowCaption);
spritePanel = new SpritePanel(bgPath);
add(spritePanel, BorderLayout.CENTER);
System.out.println(spritePanel);
bottom = new JPanel();
bottom.add(new JLabel("Hej"));
add(bottom, BorderLayout.SOUTH);
Dimension size = new Dimension(width, height);
setSize(size);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setVisible(true);
validate();
repaint();
}
class SpritePanel extends JPanel {
private static final long serialVersionUID = 1L;
private ImageIcon background;
//private ArrayList<Sprite> sprites = new ArrayList<Sprite>();
public SpritePanel(String bgPath) {
background = new ImageIcon(SpritePanel.class.getResource(bgPath));
setLayout(null);
Dimension size = new Dimension(background.getIconWidth(), background.getIconHeight());
setPreferredSize(size);
setMaximumSize(size);
setMinimumSize(size);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(background.getImage(), 0, 0, this);
System.out.println("painted panel");
}
}
}
Side Notes
setSize()
. You already pack()
. It better to just pack anyway.pack()
before the setLocationRelativeTo()
. If you pack()
after, you'll notice your frame won't be in the desired location.Run your Swing apps from the Event Dispatch Thread (EDT) like this
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
new World("Hej", "/resources/stackoverflow5.png", 1024, 768);
}
});
}
If you want to make the frame fill the screen, don't set the size. Different machines have different screen sizes. Instead use setExtendedState(JFrame.MAXIMIZED_BOTH);
setSize()
won't work anyway because you're calling pack()
after.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With