I am learning java abstract window toolkit and i am stuck in this code.When i interchange the commented line, the output changes.Any Explanation for both the cases will be appreciated.
import java.awt.*;
public class guibutton
{
public guibutton()
{
Frame f = new Frame("Panel Example");
Panel panel = new Panel();
panel.setBounds(40,80,200,200);
panel.setBackground(Color.gray);
f.add(panel);
f.setVisible(true); ////////////////this line
f.setLayout(null); /////////////////this line
f.setResizable(true);
f.setSize(400,400);
}
public static void main(String args[])
{
new guibutton();
}
}
This line:
f.setVisible(true);
renders your GUI in its current state, one where the JFrame's default BorderLayout is in force. Note that BorderLayout ignores the setBounds(...) method.
This line:
f.setLayout(null);
removes the JFrame contentPane's BorderLayout, and so your GUI is rendered without the layout, changing the positioning of the added JPanel -- the setBounds(...) method call here is respected.
If you call this after the GUI has been rendered, it won't have an effect, unless you do something that triggers the layout managers to re-layout the components, such as re-size the GUI.
Myself, I wouldn't use AWT but would use Swing, I'd draw the rectangle within the paintComponent method of a JPanel, using a Rectangle object. This way, I could monitor the mouse in relation to the rectangle, and change its state. For instance, try out this program, and see what happens to the rectangle when the mouse hovers over it:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class GuiButton2 extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private static final int RECT_X = 40;
private static final int RECT_Y = 80;
private static final int RECT_W = 200;
private static final Color DEFAULT_RECT_COLOR = Color.GRAY;
private static final Color HOVER_RECT_COLOR = Color.PINK;
private Rectangle rectangle = new Rectangle(RECT_X, RECT_Y, RECT_W, RECT_W);
private boolean hover = false;
public GuiButton2() {
setPreferredSize(new Dimension(PREF_W, PREF_H));
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
// hover true if mouse is hovering over the rectangle
hover = rectangle.contains(e.getPoint());
repaint();
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// if hover true -- use hover color, otherwise use default color
Color c = hover ? HOVER_RECT_COLOR : DEFAULT_RECT_COLOR;
g2.setColor(c);
g2.fill(rectangle); // draw rectangle
}
private static void createAndShowGui() {
GuiButton2 mainPanel = new GuiButton2();
JFrame frame = new JFrame("GUI Button");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
Side note 1:
While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
Side note 2:
You will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.
Related
package Main;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
public class Main extends JFrame{
public static void main(String[] args) {
int width = 800;
int height = 600;
String title = "Test";
JFrame display = new JFrame();
display.setTitle(title);
display.setSize(width, height);
display.setVisible(true);
display.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void paint(Graphics g) {
g.setColor(Color.white);
g.drawLine(0, 100, 800, 300);
getContentPane().setBackground(Color.black);
}
}
I'm using Java's JFrame. So this isn't recognising the paint method and cant figure out why. I've been looking on YouTube videos and having a look to see if anyone has had similar problems, however everything I've found doesn't seem to help the problem.
when i set the background colour in the main part, it works, bit in paint, it doesn't seem to do anything and leaves it blank.
Its a white line over a black background, so i should easily be able to see it.
Admittedly, I don't know much about Swing (I prefer JavaFX). However, it's clear that your Main class is a JFrame, so you should not make a new one within it. All of those methods you call on display are built in your current class. Basically, within your JFrame you made a new JFrame. However, your paint method was being called on the parent JFrame, which you never made visible. This solves your problem (you may have to fullscreen the window):
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
public class Main extends JFrame{
public static void main(String[] args) {
new Main();
}
public Main() {
int width = 800;
int height = 600;
String title = "Test";
setTitle(title);
setSize(width, height);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.WHITE);
g.drawLine(100, 100, 800, 300);
getContentPane().setBackground(Color.black);
}
}
You are creating an instance of JFrame with
JFrame display = new JFrame();
But the JFrame class has no logic to draw a white line on a black background. That logic is in your custom class Main. So instead, you should create an instance of Main:
JFrame display = new Main();
However, that change along still won't fix the problem because you are setting the background color of the "content pane" but trying to draw directly on the JFrame itself. The preferred solution here is to extend JPanel instead of JFrame and override its paintComponent() method. Then create an instance of your new class to use as the content pain:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainPanel extends JPanel{
public static void main(String[] args) {
int width = 800;
int height = 600;
String title = "Test";
JFrame display = new JFrame();
display.setTitle(title);
display.setSize(width, height);
display.setVisible(true);
display.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
display.setContentPane(new MainPanel());
}
public MainPanel() {
setBackground(Color.black);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.white);
g.drawLine(0, 100, 800, 300);
}
}
Notes:
I call setBackground() in the constructor because it does not rely on the Graphics instance passed to paintComponent(). This also avoids the overhead of another function call for each render.
In paintComponent(), I call super.panitComponent(). This allows JPanel to clear the area to be painted and any other necessary initialization.
This should be simple enough, yet I can't make it work.
I have two classes, one which should draw a circle, and the other which sets up a frame and panel with a button. On clicking the button, a circle should appear on the frame. I am confused as to why it doesn't appear. It's probably something very simple, sorry.
package ballsOnPane;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Display implements ActionListener{
private JFrame frame;
private JPanel panel;
private JButton button;
public static void main(String[] args) {
Display display = new Display();
}
public Display() {
frame = new JFrame();
frame.setSize(800, 500);
frame.setTitle("Show balls");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
panel = new JPanel();
frame.add(panel, BorderLayout.CENTER);
button = new JButton("New Ball");
frame.add(button, BorderLayout.SOUTH);
button.addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
Ball ball = new Ball(100, 100, 50);
panel.add(ball);
}
}
and ball class:
package ballsOnPane;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import javax.swing.JPanel;
public class Ball extends JPanel{
private int x;
private int y;
private int r;
public Ball(int x, int y, int r){
this.x = x;
this.y = y;
this.r = r;
}
public void paintComponent(Graphics g) {
Graphics2D g2 =(Graphics2D) g;
Ellipse2D circ = new Ellipse2D.Float(x, y, r, r);
g2.draw(circ);
}
}
When you add components to a visible GUI the basic code is:
panel.add(...);
panel.revalidate(); // to invoke the layout manager
panel.repaint(); // to repaint the components
Otherwise the size of the components added is (0, 0) so there is nothing to paint. The same goes for the button. It should be added BEFORE the frame is visible, or you need to do the revalidate()/repaint() as well.
In this case you also have a second problem:
frame.add(panel, BorderLayout.CENTER);
First you add an empty panel to the CENTER of the BorderLayout, then when you click the button you add the Ball to the CENTER.
Swing will paint the last component added first. So the ball gets painted and then the empty panel gets painted over top.
Get rid of the panel, it serves no purpose.
Edit:
For some reason I thought you were adding the Ball to the frame instead of the panel when you clicked the button.
My explanation above was correct if you did in fact add the Ball directly to the frame.
However, my explanation is incorrect since your code in the ActionListener does add the Ball to the panel. The proper explanation is below.
When you add the Ball to the panel, you don't see the Ball because by default a JPanel uses a FlowLayout and the FlowLayout respects the preferred size of any component added to it. You did not implement the getPreferredSize() method so the size is (0, 0) so there is nothing to paint.
So if you do implement the getPreferredSize() method in your Ball class the Ball will dislay on the panel. Also, you will be able to display a new Ball every time you click on the button.
As camickr answered, you need to revalidate() (or call both invalidate() & validate(), both will work) and then repaint() the panel.
The invalidate method marks the panel as being ''incorrect''; basically marking it for inspection.
Validate performs the layout of the component.
Revalidate does both, however, validate is synchronous whilst revalidate is not.
After you've validated the panel, you'll need to call repaint to redraw that panel.
As a side-note, JavaFX is replacing Swing/AWT, and in my opinon, is easier to use. You may want to look into it. :)
A short code example to do something similar to what you're currently doing, in JavaFX:
public class test extends Application{
Scene scene;
#Override
public void start(Stage primaryStage) throws Exception{
StackPane root = new StackPane();
root.setBackground(
new Background(new BackgroundFill(Color.ALICEBLUE,null,null)));
Button begin = new Button("Add Circle");
begin.setOnAction((ActionEvent e)->{
Circle c = new Circle(200,200,100,Color.RED);
root.getChildren().add(c);
});
root.getChildren().add(begin);
scene = new Scene(root, 700, 700);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I'm trying to make a JComponent opaque in the right border.
I want make a object with my specific characteristics so i'm using a JComponent that can be opaque
this is because I will make a library, and I don't want to use JPanel or JLabel
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
public class ProbadorCodigos {
JFrame Frame=new JFrame();
JComponent BORDEDE=new JComponent() {private static final long serialVersionUID = 2222L;};
public ProbadorCodigos() {
Frame.setSize(500, 500);
Frame.setResizable(false);
Frame.setUndecorated(false);
Frame.setLayout(null);
Frame.setLocationRelativeTo(null);
Frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Frame.getContentPane().setBackground(Color.darkGray);
Format();
Action();
}
private void Format() {
BORDEDE.setBounds(Frame.getWidth()-100, 0, 100, Frame.getHeight());
BORDEDE.setOpaque(true);
BORDEDE.setVisible(true);
BORDEDE.setEnabled(true);
BORDEDE.setFocusable(true);
BORDEDE.setBackground(Color.red);
System.out.println(BORDEDE);
}
private void Action() {
Frame.add(BORDEDE);
}
public static void main(String[] args) {
ProbadorCodigos Ventana=new ProbadorCodigos();
Ventana.Frame.setVisible(true);
}
}
I don't know why it don't shows opaque, if I use a JLabel works so what I missing?
thanks for your advices and answers
My suggestion for general ease of solving your problem: use a JPanel. Until you show good reason for not using this as the basis for your class, it remains in my mind the best solution for your problem. Otherwise, you'll need some code like:
JComponent bordede = new JComponent() {
private static final long serialVersionUID = 2222L;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
g.setColor(getBackground());
g.fillRect(0, 0, width, height);
}
};
Which again is not necessary if you simply used a JPanel.
Other problems with your code:
Your code does not comply with Java naming conventions and so will confuse other Java programmers.
You are using a null layout and setBounds(...) which will result in the creation of a rigid hard to enhance and debug GUI. You should avoid using this type of layout.
Sorry about my English, and my ignorance in programming, its because I'm new at this , and I'm having problem with Buttons and JFrame, please help me ;)
I'll post the print of the problem, and the codes of my the two classes I have so far, Game and Menu, hope you guys can solve it, I want the buttons to paint inside the gray panel.
Thanks.
Print of my Problem
Print
(GAME CLASS)
package br.com.lexo.dagame;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.JFrame;
import br.com.lexo.dagame.menu.Menu;
public class Game extends Canvas implements Runnable {
private static final long serialVersionUID = 1L;
private static int width = 300;
private static int height = width / 16 * 9;
private static int scale = 3;
private static String title = "Da Game";
private Thread thread;
public JFrame janela;
private Menu menu;
private boolean running = false;
public Game() {
Dimension size = new Dimension(width * scale, height * scale);
setPreferredSize(size);
janela = new JFrame();
menu = new Menu(janela, this);
}
private synchronized void start() {
if (running) return;
running = true;
thread = new Thread(this, "Thread_01");
thread.start();
}
private synchronized void stop() {
if (!running) return;
running = false;
try {
thread.join();
} catch (Exception e) {
e.printStackTrace();
}
}
public void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null){
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.setColor(Color.LIGHT_GRAY);
g.fillRect(0, 0, getWidth(), getHeight());
g.dispose();
bs.show();
}
public void update() {
}
public void run() {
while (running){
render();
update();
}
stop();
}
public static void main(String[] args) {
Game game = new Game();
game.janela.add(game);
game.janela.setTitle(title);
game.janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.janela.pack();
game.janela.setLocationRelativeTo(null);
game.janela.setResizable(false);
game.janela.setVisible(true);
game.start();
}
}
(MENU CLASS)
package br.com.lexo.dagame.menu;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import br.com.lexo.dagame.Game;
public class Menu extends Canvas {
private static final long serialVersionUID = 1L;
public boolean inMenu = false;
JButton startGame = new JButton("Começar Jogo");
JButton exitGame = new JButton("Sair do Jogo");
JButton howToPlay = new JButton("Como Jogar");
private Game game;
public Menu(JFrame janela, Game game){
this.inMenu = true;
this.game = game;
game.janela.setLayout(new GridBagLayout());
game.janela.add(startGame);
game.janela.add(exitGame);
game.janela.add(howToPlay);
howToPlay.setEnabled(false);
}
#Override
public void paint(Graphics g) {
super.paint(g);
}
}
I don't know what are you trying to accomplish but you are not adding the components correctly:
Look at:
game.janela.setLayout(new GridBagLayout());
game.janela.add(startGame);
game.janela.add(exitGame);
game.janela.add(howToPlay);
This is incorrect, the add method has two arguments, like this: container.add(component, constraints); your error is not specifying the constraints. The constraints contains all the details to know where in the panel you want to add that component.
For each LayoutManager the Object constraints is diferent. For the GridBagLayout the constraints is a GridBagConstraints object.
However GridBagLayout is a the most difficult layout to use and you don't really need it. I recommend you to look at this visual guide pick a layout and learn it properly. The tutorial for each LayoutManager explains what do you need to put in the constraints parameter.
The call container.add(component) exists because sometimes the LayoutManager does not need extra information (like the BoxLayout), in the other cases it just uses the "default" constraints for the LayoutManager in use, which may not be what you need.
For example the line in your main:
game.janela.add(game);
Is correct, but what it actually does is calling game.janela.add(game, defaultConstraints); where defaultConstraints is the default constraints value for the LayoutManager of the JFrame janela. Because you didn't explicitely specify a layout for the frame it is using the default layout for JFrames: BorderLayout, and the default constraints for the BorderLayout is the constant BorderLayout.CENTER.
So what that line actually does is:
game.janela.add(game, BorderLayout.CENTER);
Which incidentally is what you wanted to do.
To summarize:
Most calls to add must have two parameters: the component and the constraints. Each LayoutManager uses different constraints. You must be aware of what means to not specify the constraints for your LayoutManager. Do not start learning about how to properly use LayoutMangers with the GridBagLayout it's much more complex.
A quick way to somehow paint components to a graphics object is calling the paint method of component class. So in your render method:
g.fillRect(0, 0, getWidth(), getHeight());
menu.startGame.paint(g);
...
But as you'll soon see that everything is painted on the top left as components are laid out as said in the other answer and to get everything working to how you want them to work is a bit more complicated.
Now the following advice is based on my limited knowledge and was quickly put together so there are probably better ways.
About the menu class:
You are extending java.awt.Canvas when I think it would be best to extend a container like javax.swing.JPanel as you want it (I assume) to hold those 3 buttons.
Next would be to set the appropriate layout for this application, which would be null. So instead of:
game.janela.setLayout(new GridBagLayout());
it would now be:
setLayout(null);
This is because you want components (which are those buttons) to be paint on top of another component which is the Game class that extends Canvas and null allows you to do that.
Because the layout is now null, you must specify the bounds of the components which are the x and y coordinates alone with the width and the height otherwise everything will just be 0, 0, 0, 0 and nothing would show up.
So in the Game's constructor
setBounds(0, 0, width * scale, height * scale);
and janela.setPreferredSize(size); instead of setPreferredSize(size);
Back in the Menu class you will have to set the bounds of the buttons like so:
Dimensions sgSize = startGame.getPreferredSize();
startGame.setBounds(50, 50, sgSize.width, sgSize.height);
I am using preferred size to get the optimal width and height of the button that was set in the buttons UI (I think).
and add them to the Menu which is now a JPanel instead of adding them to the JFrame(janela). (add(startGame);) Also, don't forget to add the game to the menu panel.
and it should work like so:
(http://i.imgur.com/7cAopvC.png) (image)
Alternatively you could make your own widget toolkit or custom layout, but I wouldn't recommend that. I had this same problem last year but ended up moving to OpenGL but anyway, I hope this has helped :)
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):
I create a new World object in the Implementation
The World-constructor is called with the given parameters
The window caption is set (this works)
I create a new SpritePanel object with the given bgPath
The SpritePanel-constructor is called and sets the ImageIcon to the image that exists in the given path
The SpritePanel is added to the frame in BorderLayout.CENTER
I add a new JPanel to the frame in BorderLayout.CENTER
I set size and stuff
I pack and set the frame to visible
I validate and repaint
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.
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
No need to setSize(). You already pack(). It better to just pack anyway.
Put the 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);
Also, your setSize() won't work anyway because you're calling pack() after.
My problem was that I hade overridden the getWidth() and getHeight() methods in my World-class.
But look to peeskillets response for how to make things better!