Eric Eric - 7 months ago 36
Java Question

Creating a scrolling background- image not showing up

I'm trying to create this JPanel with a simple moving background. The issue is that when I run my program, the background doesn't show up. After some analysis, I suspect the issue is the repaint() method inside the run() method. Though no syntax or run-time errors appear, this logic error lead me to a long time of trying to figure out what and where something went wrong.

This first class is my JFrame class. Has a method that will create a panel and add it to JFrame.

import javax.swing.*;
import java.awt.*;
//import java.awt.event.*; for later

public class UserInterface extends JFrame{

private final int WINDOW_WIDTH = 1250;
private final int WINDOW_HEIGHT = 750;

public UserInterface(){
super("idk");
setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setLocationRelativeTo(null);
add(startScreen());
setVisible(true);
}

public JPanel startScreen(){
JPanel panel;
JLabel title;
JButton begin;

int beginSizeX = 400;
int beginSizeY = 50;

//using absolute positioning
panel = new JPanel(null);

title = new JLabel("idk");
begin = new JButton("Begin");

title.setFont(new Font("Consolas", Font.PLAIN, 250));

title.setBounds(WINDOW_WIDTH / 4, WINDOW_HEIGHT / 4, 700, 200);
begin.setBounds((WINDOW_WIDTH / 2) - (beginSizeX / 2),
(WINDOW_HEIGHT / 2) - (beginSizeY / 2), beginSizeX, beginSizeY);

//these objects are commented out so i can focus on the problem- getting background to appear (though only these two objects have no problem appearing)
//panel.add(title);
//panel.add(begin);

titlePageBackground.ScrollingBackground background = new titlePageBackground.ScrollingBackground();
background.setFocusable(true);
panel.add(background);
return panel;

}//startScreen
}//UserInterface


This next class probably holds background image and the draw method for repainting the background. Shouldn't be the issue I suspect.

package titlePageBackground;

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;

public class Background {

private BufferedImage image;
private int xPos;
private int yPos;

//default constructor
public Background() {
this(0,0);
}

//standard constructor
public Background(int xPos, int yPos) {
this.xPos = xPos;
this.yPos = yPos;

try {
String imageFilePath = System.getProperty("user.dir") + "\\src\\titlePageBackground\\background.png";
image = ImageIO.read(new File(imageFilePath));
}
catch (Exception e) { System.out.println(e.getMessage()); }
}

public void draw(Graphics g) {
g.drawImage(image, getXPos(), getYPos(), image.getWidth(), image.getHeight(), null);

this.xPos -= 5;

if (this.xPos <= -1 * image.getWidth())
this.xPos = this.xPos + image.getWidth() * 2;
}//draw

public void setXPos(int xPos) {
this.xPos = xPos;
}
public void setYPos(int yPos){
this.yPos = yPos;
}

public int getXPos() {
return this.xPos;
}
public int getYPos() {
return this.yPos;
}

public int getImageWidth() {
return image.getWidth();
}
public int getImageHeight() {
return image.getHeight();
}

public String toString() {
return "Background: xPos = " + getXPos() + ", yPos = " + getYPos() +
", height = " + image.getHeight() + ", width = " + image.getWidth();
}

}//Background


This is where things get nasty. Take a look at the run() method.

package titlePageBackground;

import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

public class ScrollingBackground extends Canvas implements Runnable {

//reason for two backgrounds due to scrolling mechanism must scroll past image one,
//resulting in second need for one of other background coexisting on current panel
private Background backgroundOne;
private Background backgroundTwo;

private BufferedImage bufferedBackground;

//standard constructor
public ScrollingBackground() {
backgroundOne = new Background();
backgroundTwo = new Background(backgroundOne.getImageWidth(), backgroundOne.getYPos());
new Thread(this).start();
setVisible(true);
}

@Override
public void run() {
try {
while (true) {
Thread.currentThread().sleep(5);
repaint();
}//while
} catch (Exception e) {
System.out.println(e.getMessage());
}
}//run

@Override
public void update(Graphics g) {
paint(g);
}

public void paint(Graphics g) {
Graphics2D graphics2D = (Graphics2D)g;

if (bufferedBackground == null)
bufferedBackground = (BufferedImage)(createImage(getWidth(), getHeight()));

Graphics buffer = bufferedBackground.createGraphics();

//Loading images into the buffer for output
backgroundOne.draw(buffer);
backgroundTwo.draw(buffer);

graphics2D.drawImage(bufferedBackground, null, 0, 0);
}//paint
}//ScrollingBackground


The idea here is that two images are created and move at an interval of 5 pixels. When one image moves too far left to where the whole image is out of the panel, it moves to the very right to repeat until it gets to far out of frame.

Recap: Why isn't my background image showing up?

__________Problem Solved, New Scrolling Background class (below should work)_________

public class ScrollingBackground extends Canvas implements Runnable {

//reason for two backgrounds due to scrolling mechanism must scroll past image one,
//resulting in second need for one of other background coexisting on current panel
private Background backgroundOne;
private Background backgroundTwo;

private BufferedImage bufferedBackground;

//standard constructor
public ScrollingBackground() {
backgroundOne = new Background();
backgroundTwo = new Background(backgroundOne.getImageWidth(), backgroundOne.getYPos());
setSize(backgroundOne.getImageWidth() * 2, backgroundOne.getImageHeight());
new Thread(this).start();
setVisible(true);
}

@Override
public void run() {
try {
while (true) {
Thread.currentThread().sleep(50);
repaint();
}//while
} catch (Exception e) {
System.out.println(e.getMessage());
}
}//run

@Override
public void update(Graphics g) {

Graphics2D graphics2D = (Graphics2D)g;

if (bufferedBackground == null)
bufferedBackground = (BufferedImage)(createImage(getWidth(), getHeight()));

Graphics buffer = bufferedBackground.createGraphics();

//Loading images into the buffer for output
backgroundOne.draw(buffer);
backgroundTwo.draw(buffer);

paint(graphics2D);
}//update

public void paint(Graphics2D graphics2D) {
graphics2D.drawImage(bufferedBackground, 0, 0, null);
}
}//ScrollingBackground

Answer

How about

graphics2D.drawImage(bufferedBackground, 0, 0, null);

What you are using is

drawImage(BufferedImage img, BufferedImageOp op, int x, int y)

while you meant is

drawImage(Image img, int x, int y, ImageObserver observer)

You also need to set the size of the Canvas (in ScrollingBackground constructor):

setSize(2*backgroundOne.getImageWidth(), backgroundOne.getImageHeight());