Having images as background of JPanel
Why not make a single class that takes a Image
??
public class ImagePane extends JPanel {
private Image image;
public ImagePane(Image image) {
this.image = image;
}
@Override
public Dimension getPreferredSize() {
return image == null ? new Dimension(0, 0) : new Dimension(image.getWidth(this), image.getHeight(this));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(image, 0, 0, this);
g2d.dispose();
}
}
You would even provide hints about where it should be painted.
This way, you could simply create an instance when ever you needed it
Updated
The other question is, why?
You could just use a JLabel
which will paint the icon for you without any additional work...
See How to use labels for more details...
This is actually a bad idea, as JLabel
does NOT use it's child components when calculating it's preferred size, it only uses the size of the image and the text properties when determining it's preferred size, this can result in the component been sized incorrectly
Why is my image (and child components) not showing with ImageBackground on React Native?
Answered! The answer was to add flex: 1 to the parent view container - for those running into the same problem.
Background image not showing in Java Game
Let's start with...
backgroundImage = new BackgroundImage("/background.png");
Which becomes...
File image2 = new File(path);
or
File image2 = new File("/background.png");
so you can see it...can you see a problem with this? This is requesting a file which resides at the root location of the current drive...not really what I think you want...
The images are stored in a folder called "res" in the main project folder
Which would suggest you want to use...
backgroundImage = new BackgroundImage("res/background.png");
Assuming that the images are not embedded resources....
Next...
public BackgroundImage(String s) {
if (s == null) {
background = getImage(s);
}
}
So, you only ever want to try a load the image when it's reference is null
???
Side notes...
frame.setSize(WIDTH * SCALE, HEIGHT * SCALE);
is a bad idea, as frames have borders which occupy space within side the frame itself.
Better to override the getPreferredSize
method of Canvas
and provide a default size value you want to use and then call pack
on the frame instead. This will calculate the size of the frame as the preferred size of it's content PLUS the frame border requirements...
You "game loop" is running wild...
while (running) {
delta += (now - lastTime) / ns;
lastTime = now;
if (delta >= 1) {
tick();
delta--;
}
render();
}
Basically, this will run as fast as it possibly can and will reduce the opportunity for other threads to run, eventually bringing your game (and probably your PC) to it's knees
This is "simple" concept of a run loop...
public void run() {
init();
final long amountOfTicks = 60;
long ns = Math.round(1_000_000_000 / (double)amountOfTicks);
int frames = 0;
long frameStart = System.currentTimeMillis();
while (running) {
long startedAt = System.nanoTime();
tick();
render();
long completedAt = System.nanoTime();
long duration = completedAt - startedAt;
long frameEnd = System.currentTimeMillis();
if (frameEnd - frameStart >= 1000) {
System.out.println(frames);
frames = 0;
frameStart = System.currentTimeMillis();
} else {
frames++;
}
long rest = ns - duration;
if (rest > 0) {
rest = TimeUnit.MILLISECONDS.convert(rest, TimeUnit.NANOSECONDS);
try {
Thread.sleep(rest);
} catch (InterruptedException ex) {
}
}
}
stop();
}
Basically, it tries to ensure that there is enough delay between each iteration in order to maintain the 60fps you are trying to target...without starving the system...
JFrame not showing a picture
There are so many things wrong with this I'm not sure where to start...
Let's start at the beginning...
Problem #1
You declare a instance field called steve
in you WindowPractice
class, this is fine, but in your main method, you declare ANOTHER variable called steve
which you are using the reference to the loaded image...
public static void main(String[] args) {
new WindowPractice();
ImageIcon steve = new ImageIcon("C:/Users/shane/Dropbox/issue459.jpg");
JLabel imageLabel = new JLabel(steve);
}
This means that the class instance variable is never initialised and remains null
.
Problem #2
While not directly related, you never call super.paint
from your paint
method. This is a BIG NO, NO. You are obligated to maintain the paint chain. The paint methods are complex and very, very important.
Problem #3
You should never override a top level container (such as JFrame
) nor you should you override any of it's paint
methods. There are lots of reasons for this, but among the top two are, most top level containers actually contain a number of components (JRootPane
, which houses the glass pane, content pane, layer pane and menu bar) which can sit over your painting efforts and, generally, they're not double buffered, meaning you paint updates will flicker and look horrible ;)
You should also avoid using paint
, instead, you should look towards using paintComponent
where it's available.
Problem #4
ImageIcon
is not you best choice for loading images. The main reason I don't use them is that you have no idea of when the image being loaded will actually become available (actually there are ways, but to be frank, ImageIO
is just simpler). This was a great feature back in 1999 when dial-up speeds where around the 14.4k mark, but now days...
ImageIO
supports a wider range of picture formats, supports reading and writing of images and guarantees that when the method returns (successfully), the image pixel data is available to your application.
Example
Here's a better (IMHO) approach...
public class BetterDrawing {
public static void main(String[] args) {
new BetterDrawing();
}
public BetterDrawing() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new PaintPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PaintPane extends JPanel {
private BufferedImage background;
public PaintPane() {
try {
background = ImageIO.read(new File("/path/to/image"));
// Use this instead to load embedded resources instead
//background = ImageIO.read(getClass().getResource("/path/to/image"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Override
public Dimension getPreferredSize() {
return background == null ? super.getPreferredSize() : new Dimension(background.getWidth(), background.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g.drawImage(background, x, y, this);
}
}
}
}
Have a read of
- Performing custom painting
- Working with Images
For some more information.
Related Topics
Compare Two Objects With .Equals() and == Operator
How to Set the Environment Variables For Java in Windows
How to Add Jars to Maven 2 Build Classpath Without Installing Them
Java Serializable Object to Byte Array
How Does the "Final" Keyword in Java Work (I Can Still Modify an Object.)
What Is the Purpose of the Expression "New String(...)" in Java
How to Open a New Tab Using Selenium Webdriver in Java
"Invalid Signature File" When Attempting to Run a .Jar
Equals VS Arrays.Equals in Java
Jtextfields on Top of Active Drawing on Jpanel, Threading Problems
How to Remove Objects from an Array in Java
Difference Between Inheritance and Composition