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:
Some recommendations:
Since I'm guessing that your CarAnimatorJPanel sits on top of a background JPanel, you'd better set CarAnimatorJPanel to be non-opaque via setOpaque(false) so that the JPanel behind it can be seen.
When adding components to a JLayeredPane, you're essentially adding the components to a null layout. This means that you absolutely need to set the sizes (or override getSize()) of those components, not the preferred sizes.
As always, when dealing with image files, debug that you're able to adequately read in the image in a separate small test program. As usual, consider getting the image in as a resource and not as a File.
You have some program logic code in your 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.
Related
I'm sure this is a simple answer, but I can't figure it out.
I am trying to make a basic shape that I can control in a window. Obviously it will be more involved when the whole project is complete, but I am working on the early steps still. I am using WindowBuilder to make the layout, and have a JPanel and a JButton. The JPanel draws a rectangle, and has a method to move it. The JButton calles that moving command. And that's it. The problem is in the repaint. The shape keeps all old versions of itself, and the button makes weird copies of itself. All these go away when I resize the window, which I thought was the same as calling repaint. Again, I'm sure is something simple I am missing. Below are my 2 classes.
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.BorderLayout;
import javax.swing.JPanel;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Drawing {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Drawing window = new Drawing();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Drawing() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
drawpanel panel = new drawpanel();
panel.setBounds(58, 68, 318, 182);
frame.getContentPane().add(panel);
JButton btnMove = new JButton("move");
btnMove.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
panel.moves();
}
});
btnMove.setBounds(169, 34, 89, 23);
frame.getContentPane().add(btnMove);
}
}
^ This one, besides the buttonListener, was autocreated by WindowBuilder.
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class drawpanel extends JPanel {
int x = 50, y = 50;
int sizeX = 50, sizeY = 50;
public void paintComponent( Graphics g) {
super.paintComponents(g);
g.setColor(Color.BLACK);
g.drawRect(x, y, sizeX, sizeY);
}
public void moves() {
x +=5;
repaint();
}
}
^ This one has my drawing of the shape and the moving/repainting method. It was written mostly from other examples I found on this site.
Thanks to any help in advanced.
public void paintComponent(Graphics g) {
super.paintComponents(g); // wrong method! (Should not be PLURAL)
Should be:
public void paintComponent(Graphics g) {
super.paintComponent(g); // correct method!
In an attempt to make a very simple bullet-hell game to learn about java, I ran into a roadblock: repaint() wasn't calling paintComponent().
Here is the entire program, which for now simply draws an image I created 50 times per second onto a JPanel, which rests on a JFrame.
/*
* Bullet hell, by Nematodes
*/
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class bulletHell extends JFrame
{
private static final long serialVersionUID = 0L;
JPanel gamePanel = new JPanel();
int gameTimerDelay = 20;
int x, y = 0;
BufferedImage lightOrb;
javax.swing.Timer gameTimer;
public static void main(String[] args)
{
bulletHell createFrame = new bulletHell();
createFrame.frameConstructor();
}
public void frameConstructor()
{
// Construct frame and frame components
setTitle("Bullet hell");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
getContentPane().setLayout(new GridBagLayout());
setVisible(true);
GridBagConstraints gridConstraints;
gridConstraints = new GridBagConstraints();
gridConstraints.gridx = 0;
gridConstraints.gridy = 0;
gamePanel.setBackground(Color.BLACK);
gamePanel.setPreferredSize(new Dimension(700, 700));
getContentPane().add(gamePanel, gridConstraints);
pack();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setBounds((int) (0.5 * (screenSize.width - getWidth())),
(int) (0.5 * (screenSize.height - getHeight())), getWidth(), getHeight());
try
{
lightOrb = ImageIO.read(new File("C:/Users/Owner/Downloads/orb.bmp"));
}
catch(IOException e)
{
System.out.println("An issue occurred while trying to read orb.bmp");
}
// Start timer that draws game objects 50 times per second (50 FPS)
gameTimer = new javax.swing.Timer(gameTimerDelay, gameTimerAction);
gameTimer.setInitialDelay(0);
gameTimer.start();
}
ActionListener gameTimerAction = new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
repaint();
}
};
class GraphicsPanel extends JPanel
{
public GraphicsPanel()
{
}
// Draw all of the components
#Override
public void paintComponent(Graphics g)
{
Graphics2D g2D = (Graphics2D) g;
super.paintComponent(g2D);
g2D.drawImage(lightOrb, x, y, this);
g2D.dispose();
}
}
}
After some debugging with breakpoints and println methods, I can confirm that the correct image is being read, the timer in gameTimerAction is being called 50 times per second, and repaint() is not invoking paintComponent() at all.
I am somewhat new to Java programming, and might just be missing something simple.
Edit: Problem has been solved by changing gamePanel to a GraphicsPanel object. Unfortunately, this also means that my much larger pong project (which this project's flawed drawing logic was essentially copied from) only worked by a miracle, and might be unstable with certain code additions.
I can immediately see several problems:
Most Important: You never instantiate a GraphicsPanel object, nor do you add it to anything. The paintComponent(...) method will never be called on a JPanel that is neither rendered nor created. Why not make your gamePanel variable a GraphicsPanel object and not a JPanel object?
You never change x and y in your Timer, and so without change, no animation will occur.
Also you're calling dispose on a Graphics object given to you by the JVM, something you should never do. This breaks the Swing painting chain making the graphics of your GUI unstable.
So keep at it, you'll get there.
For example:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class BulletExample extends JPanel {
public static final String IMG_PATH = "http://www.i2clipart.com/cliparts/f/0/5/8/clipart-blue-circle-f058.png";
private static final int PREF_W = 700;
private static final int PREF_H = PREF_W;
private static final int TIMER_DELAY = 20;
private BufferedImage bullet;
private int bulletX;
private int bulletY;
public BulletExample() throws IOException {
URL imgUrl = new URL(IMG_PATH);
bullet = ImageIO.read(imgUrl);
new Timer(TIMER_DELAY, new BulletListener()).start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bullet != null) {
g.drawImage(bullet, bulletX, bulletY, this);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class BulletListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
bulletX++;
bulletY++;
repaint();
}
}
private static void createAndShowGui() throws IOException {
// create the drawing JPanel
BulletExample mainPanel = new BulletExample();
JFrame frame = new JFrame("BulletExample");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// add it to the JFrame
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
createAndShowGui();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
I have a simple gui and when I run is it is perfect, but occasionally it doesn't display right. I have a circle in a JPanel. When it runs right it displays in the middle for the JFrame like I intended it to, but when it does not work right the circle appears closer to the bottom of the screen. How can I fix this so it displays right each time? Is my code incorrect (I hope not! :) ), or is it some bug in java. So here is my code:
Update: It seems that the window height is changing.
Run.java--------------------------------------------------------------------------------
import javax.swing.JFrame;
public class Run {
public static void main(String args[]) {
Window w = new Window();
w.setSize(800, 500);
w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
w.setVisible(true);
}
}
Window.java----------------------------------------------------------------------------
import javax.swing.JFrame;
public class Window extends JFrame {
public Window() {
super("Wheel");
Gui g = new Gui();
add(g);
}
}
Gui.java--------------------------------------------------------------------------------
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Gui extends JPanel {
private Color wheelColor = new Color(0, 0, 255);
public Gui() {
setOpaque(true);
setBackground(new Color(255, 0, 0));
}
public void paintComponent(Graphics g) {
g.setColor(wheelColor);
g.fillOval(40, 40, 420, 420);
}
}
Also I'm using Ubuntu, I don't know if that would affect it at all. Thanks in advance.
Make sure you create the UI within the context of the Event Dispatching Thread, see Initial Threads for more details.
Make sure you are calling super.paintComponent within the paintComponent method before you do any custom painting, see Painting in AWT and Swing for more details
Don't rely on magic numbers, the size of the window is the size of it's content + its frame decorations. You should get using getWidth and getHeight to determine the size of the Gui panel and overriding getPreferredSize to allow the window to determine how much room it needs to (optimally) display it
For example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Run {
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Window w = new Window();
w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
w.pack();
w.setLocationRelativeTo(null);
w.setVisible(true);
}
});
}
public static class Window extends JFrame {
public Window() {
super("Wheel");
Gui g = new Gui();
add(g);
}
}
public static class Gui extends JPanel {
private Color wheelColor = new Color(0, 0, 255);
public Gui() {
setOpaque(true);
setBackground(new Color(255, 0, 0));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(440, 440);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(wheelColor);
int width = getWidth();
int height = getHeight();
int x = (width - 420) / 2;
int y = (height - 420) / 2;
g.fillOval(x, y, 420, 420);
}
}
}
Also beware of naming your classes after classes that already exist within the default API, java.awt.Window already exists and can cause confusion not only for yourself, but for other developers ;)
Ok so basically I'm trying to write a GUI application which draws 2 circles and 2 rectangles in its main window. I'm trying to get it so that whenever the user clicks within the circles or rectangles, that particular circle or rectangle changes to another random colour.
Currently I've got it so that the MouseClick event (anywhere on screen) causes all of the circles or rectangles to change colour, to the same colour.
This is what I've got so far:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Question2 {
public static void main(String[] args) {
SecondFrame f = new SecondFrame("Draw and Fill");
f.init();
}
}
class SecondFrame extends JFrame{
SecondFrame(String title) {
super(title);
}
private JPanel mainPanel;
private GridBagConstraints gbc = new GridBagConstraints();
private GridBagLayout gbLayout = new GridBagLayout();
void init() {
mainPanel = new JPanel();
mainPanel.setLayout(gbLayout);
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
this.setContentPane(mainPanel);
gbc.gridheight = 1;
mainPanel.addMouseListener(new MouseListener(){
#Override
public void mouseClicked(MouseEvent e) {
Point mousePosition;
mousePosition = mainPanel.getMousePosition();
repaint();
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
});
this.pack();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public void paint(Graphics g){
super.paint(g);
Random ran = new Random();
// Assumes max and min are non-negative.
int red = 0 + ran.nextInt(255 - 0 + 1);
int green = 0 + ran.nextInt(255 - 0 + 1);
int blue = 0 + ran.nextInt(255 - 0 + 1);
Color myColor = new Color(red,green,blue);
g.setColor(myColor);
g.fillOval(50,50,200,200);
g.fillOval(50, 255, 200, 200);
g.fillRect(255,50,200,200);
g.fillRect(255, 255, 200, 200);
}
}
If you could point me in the right direction that would be much appreciated. Thanks.
You would keep a track of drawn object. Then check if click occurred within any of these objects. If yes, change its color. For example, you can use Shape to represent simple forms. Its contains() method can be useful to determine if a clicked point is inside the boundary of the shape. Below is an example that introduces ShapeItem that has two properties Shape and Color. And, a panel that uses a list of ShapeItem to paint the actual shapes.
Also consider some minor side notes:
Don't paint directly on top level container such as JFrame. Instead, use JPanel or extension of JComponent;
For painting override paintComponent() rather than paint(), and don't forget to call super.paintComponent(g);
Usually there is no need to extend JFrame unless new functionality is added;
Take a look at Performing Custom Painting tutorial, and Closer Look at the Paint Mechanism section in particular, for more details.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class DemoShapes {
public static final Color DEFAULT_COLOR = Color.BLUE;
public DemoShapes() {
List<ShapeItem> shapes = new ArrayList<ShapeItem>();
shapes.add(new ShapeItem(new Rectangle2D.Double(110, 1, 100, 100),
DEFAULT_COLOR));
shapes.add(new ShapeItem(new Rectangle2D.Double(110, 110, 100, 100),
DEFAULT_COLOR));
shapes.add(new ShapeItem(new Ellipse2D.Double(1, 1, 100, 100),
DEFAULT_COLOR));
shapes.add(new ShapeItem(new Ellipse2D.Double(1, 110, 100, 100),
DEFAULT_COLOR));
JFrame frame = new JFrame("Shapes");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ShapesPanel panel = new ShapesPanel(shapes);
frame.add(panel);
frame.setLocationByPlatform(true);
frame.pack();
frame.setVisible(true);
}
class ShapeItem {
private Shape shape;
private Color color;
public ShapeItem(Shape shape, Color color) {
super();
this.shape = shape;
this.color = color;
}
public Shape getShape() {
return shape;
}
public void setShape(Shape shape) {
this.shape = shape;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
}
class ShapesPanel extends JPanel {
private List<ShapeItem> shapes;
private Random rand = new Random();
public ShapesPanel(List<ShapeItem> shapesList) {
this.shapes = shapesList;
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
Color color = getRandomColor();
for (ShapeItem item : shapes) {
if (item.getShape().contains(e.getPoint())) {
item.setColor(color);
}
}
repaint();
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
for (ShapeItem item : shapes) {
g2.setColor(item.getColor());
g2.fill(item.getShape());
}
g2.dispose();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
private Color getRandomColor() {
return new Color(rand.nextFloat(), rand.nextFloat(),
rand.nextFloat());
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new DemoShapes();
}
});
}
}
You should use mousePosition to determine if that point is within the bounds of any ovals or rectangles. If it is, perform g.setColor(myColor) and fill that shape. Then change g to a normal, non-randomized color, and fill the rest of the shapes.
Eventually after I work out this small detail it will receive a building and room number to outline said building and room number so it is easy to locate but I can't get the rectangle to draw even close to acurately over a single room.
package programSTLApp;
/*
Program to request the classroom no. in STLCC and Display the location of
that classroom.
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class STLApp extends JFrame
{
private JLabel imageLabel;
private JButton button;
private JPanel imagePanel;
private JPanel buttonPanel;
public STLApp()
{
super("My STLCC Class Locator");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
buildImagePanel();
buildButtonPanel();
add(imagePanel, BorderLayout.CENTER);
add(buttonPanel,BorderLayout.SOUTH);
pack();
setVisible(true);
}
private void buildImagePanel()
{
imagePanel = new JPanel();
imageLabel = new JLabel("Click the button to see the drawing indicating "
+ "the location of your class");
imagePanel.add(imageLabel);
}
private void buildButtonPanel()
{
buttonPanel = new JPanel();
button = new JButton("Get Image");
button.addActionListener(new ButtonListener());
buttonPanel.add(button);
}
private class ButtonListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
ImageIcon SiteLayoutFV = new ImageIcon("D:\\B120.jpg");
imageLabel.setIcon(SiteLayoutFV);
imageLabel.setText(null);
pack();
}
}
public void paint(Graphics g)
{
super.paint(g);
g.setColor(Color.RED);
g.fillRect(55,740,164,815);
}
public static void main(String[] args)
{
new STLApp();
}
}
As has already being pointed out, top level containers ain't a studiable class for performing custom painting, there is just to much going with these containers to make it easy to paint to.
Instead, create yourself a custom component, extending from something like JPanel, and override it's paintComponent method.
Once you have the floor pane rendered, you can render you custom elements over the top of it.
How you store this information is up to you, but basically, you need some kind of mapping that would allow you to take the floor/room and get the Shape that should be rendered.
Because the floor map might float (it may not always be rendered at 0x0 for example), you need to be able to translate the coordinates so that the Shape will always match.
Take a look at...
Performing Custom Painting
2D Graphics
For more details
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class FloorPlan {
public static void main(String[] args) {
new FloorPlan();
}
public FloorPlan() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage floorPlan;
private Rectangle myOffice = new Rectangle(150, 50, 32, 27);
public TestPane() {
try {
floorPlan = ImageIO.read(new File("floorPlan.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return floorPlan == null ? new Dimension(200, 200) : new Dimension(floorPlan.getWidth(), floorPlan.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (floorPlan != null) {
int x = (getWidth() - floorPlan.getWidth()) / 2;
int y = (getHeight() - floorPlan.getHeight()) / 2;
g2d.drawImage(floorPlan, x, y, this);
g2d.setColor(Color.RED);
g2d.translate(x, y);
g2d.draw(myOffice);
}
g2d.dispose();
}
}
}