Reputation: 311
I've been trying for a while to load an image into this JFrame for it to display it without success. Here is the code:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JOptionPane;
public class Main extends JPanel{
Bird bird = new Bird(this);
public void paint(Graphics g){
super.paint(g);
Graphics2D g2D = (Graphics2D) g;
g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
bird.paint(g2D);
}
public static void main(String[] args)throws InterruptedException{
JFrame frame = new JFrame("Java Birds");
Main game = new Main();
frame.add(game);
frame.setSize(500, 300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while(true){
game.repaint();
Thread.sleep(10);
}
}
}
This is my Bird Class:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;
public class Bird {
private static final Image sprite = Toolkit.getDefaultToolkit().getImage("bird.jpeg");
private static final int DIAMETER = 30;
double g = 0.12, vy = 0, xo = 100, yo = 10;
private Main game;
public Bird(Main game){
this.game = game;
}
public void paint(Graphics2D g){
g.setColor(Color.BLACK);
g.drawImage(sprite, 30, 30, game);
}
}
When I run this nothing shows up onscreen, but if I place a g.fillOval instruction I do get a circle in the panel. Help much appreciated, please.
Upvotes: 0
Views: 520
Reputation: 940
To display an image which fills the entire panel, you should have the following. You can use ImageIO.read(File)
to read in an image from a file (you can adjust the position and size of the image inside the paintComponent
method). You may want to also see Graphics.drawImage`.
import javax.swing.*;
import java.awt.image.*;
import java.awt.*;
public class PictureFrame extends JComponent{
private final Image img;
public PictureFrame(final String file) throws IOException {
this(new File(file));
}
public PictureFrame(final File file) throws IOException {
this(ImageIO.read(file));
}
public PictureFrame(BufferedImage img){
this.img = img;
this.setPreferredSize(new Dimension(img.getWidth(), img.getHeight()));
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(img, 0, 0, getWidth(), getHeight(), null);
}
}
Tester main:
public static final String TEST_FILE = "file path here";
public static void main(String... args) throws IOException {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
}
final JFrame frame = new JFrame();
final JComponent picture = new PictureFrame(TEST_FILE);
frame.setContentPane(picture);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 300);
frame.setVisible(true);
}
Upvotes: 0
Reputation: 347184
There are a cascade of issues, first...
public void paint(Graphics g){
super.paint(g);
Graphics2D g2D = (Graphics2D) g;
g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
bird.paint(g2D);
}
You're overriding paint
, it is highly unrecommended to do so, instead, it is recommended that you override paintComponent
instead.
Another problem is...
Toolkit.getDefaultToolkit().getImage("bird.jpeg");
The problem with this is getImage(String)
expects that the value you pass it refers to a file on the file system. In most cases, this is not true and the image is stored as an embedded resource, in which use you would need to use something more like...
Toolkit.getDefaultToolkit().getImage(Bird.class.getResource("bird.jpeg"));
or
Toolkit.getDefaultToolkit().getImage(Bird.class.getResource("/bird.jpeg"));
There is still no guarantee that the image is loaded and none of these approaches actually tells you when it has failed.
A better solution would be to use ImageIO
to read the image, apart from supporting more formats, it will throw an IOException
when it fails...
public class Bird {
private Image sprite;
//...
public Bird(Main game) throws IOException {
image = ImageIO.read(getClass().getResource("/bird.jpeg"));
This...
while(true){
game.repaint();
Thread.sleep(10);
}
Is also very dangerous, you've started this in the main
method, but you've take no consideration into what thread main
might be called in. While in "normal" operations, main
is called by the JVM from what is known as the "main thread", there is no guarantee that this is how your main
method is called. It might called by another class from the context of the EDT which would cause the program to freeze.
Generally you should either use a javax.swing.Timer
or a separate thread all together.
Upvotes: 3