Reputation: 121
I am trying to use JLayeredPane to overlay one JPanel on top of another. For some reason the added panels don't show up.
This is the code that creates the JLayeredPane and adds elements to it:
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.SwingUtilities;
public class CarAnimator extends JFrame {
public CarAnimator()
{
JLayeredPane racingOverlay = new JLayeredPane();
CarAnimatorJPanel animation = new CarAnimatorJPanel();
Racetrack racetrack = new Racetrack();
racingOverlay.add(racetrack,JLayeredPane.DEFAULT_LAYER);
racingOverlay.add(animation,new Integer(2));
racingOverlay.setBorder(BorderFactory.createTitledBorder("Can't see a thing"));
this.getContentPane().add(racingOverlay,BorderLayout.CENTER);
this.setLocationByPlatform(true);
this.setPreferredSize(new Dimension(850,650));
this.setMaximumSize(new Dimension(850,650));
this.setMinimumSize(new Dimension(850,650));
this.setResizable(false);//prevents user from resizing the window
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(() -> {
(new CarAnimator()).setVisible(true);
});
}
}
This is the code for the racing track JPanel:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Racetrack extends JPanel
{
Graphics g = this.getGraphics();
@Override
public void paintComponent(Graphics g)
{
Color c1 = Color.green;
g.setColor( c1 );
g.fillRect( 150, 200, 550, 300 ); //grass
Color c2 = Color.black;
g.setColor( c2 );
g.drawRect(50, 100, 750, 500); // outer edge
g.drawRect(150, 200, 550, 300); // inner edge
Color c3 = Color.yellow;
g.setColor( c3 );
g.drawRect( 100, 150, 650, 400 ); // mid-lane marker
Color c4 = Color.white;
g.setColor( c4 );
g.drawLine( 425, 500, 425, 600 ); // start line
}
}
And this is the JPanel animation example, taken from Java: How to Program book (http://java.uom.gr/~chaikalis/javaLab/Java_HowTo_9th_Edition.pdf), adapted to work with my code:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;
public class CarAnimatorJPanel extends JPanel
{
protected ImageIcon images[];
private int currentImage=0;
private final int ANIMATION_DELAY=50;
private int width;
private int height;
private Timer animationTimer;
public CarAnimatorJPanel()
{
try
{
File directory = new File("C://Users/eltaro/Desktop/Car images");
File[] files = directory.listFiles();
images = new ImageIcon[files.length];
for (int i=0;i<files.length;i++)
{
if (files[i].isFile())
{
images[i]=new ImageIcon(ImageIO.read(files[i]));
}
}
width = images[0].getIconWidth();
height = images[0].getIconHeight();
}
catch(java.io.IOException e)
{
e.printStackTrace();
}
}
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
images[currentImage].paintIcon(this,g,0,0);
if(animationTimer.isRunning())
{
currentImage=(currentImage+1)%images.length;
}
}
public void startAnimation()
{
if(animationTimer==null)
{
currentImage=0;
animationTimer=new Timer(ANIMATION_DELAY, new TimerHandler());
animationTimer.start();
}
else
{
if(!animationTimer.isRunning())
{
animationTimer.restart();
}
}
}
public void stopAnimation()
{
animationTimer.stop();
}
@Override
public Dimension getMinimumSize()
{
return getPreferredSize();
}
@Override
public Dimension getPreferredSize()
{
return new Dimension(width,height);
}
private class TimerHandler implements ActionListener
{
@Override
public void actionPerformed(ActionEvent actionEvent)
{
repaint();
}
}
}
When I add the two JPanels to the JLayeredPane inside CarAnimator constructor, they fail to show:
Upvotes: 1
Views: 1037
Reputation: 285405
Some recommendations:
setOpaque(false)
so that the JPanel behind it can be seen.getSize()
) of those components, not the preferred sizes.paintComponent(Graphics g)
method -- you change the state of the currentImage field. Never do this since you never have full control over when or even if paintComponent is called. This bit of code belongs in your animation loop, your Swing Timer's ActionListener.Upvotes: 2