0

So I have a "GameCourt" class that extends JPanel. This class overwrites the paintComponent code, so that it paints a few components (a maze, a character and some coins). This JPanel is part of a class extending JLayeredPane with two layers, one to paint the background (using BackgroundPanel class that extends JPanel), and another to paint all the elements I want (A reset button, a label..)

So what I want is the GameCourt that is above the Background in the JLayeredPane to not paint it's background so I can view the beautiful image.

I tried setOpaque(false) in the GameCourt,but then it only displays the background.

I tried setBackground (new Color(0,0,0,0)) but that didn't work. That's because there is another blackBackground behind the GameCourt JPanel I have no idea where it's coming from. I tried super.setBackground, but that did nothing.

I tried changing the index of the background in JLayeredPane to make it above he GameCourt(JPanel), but that doesn't make a difference. (This is weird since it should at least paint the background above the GameCourt JPanel.

Also, I tried doing: add(background, new Integer(0)) like in the sample code in the JavaDocs, but it said "Illegal Argument Exception".

I really don't know what is wrong... I think I misunderstood the JLayeredPane Code because when I use setOpaque(false) but don't add the background to the JLayeredPane, it displays everything correctly. Also, how is changing add(background,0) to add(background,2) not making a difference??

Here is the "GameCourt" code (simplified): the m.draw(g), coins.drawCoins(g), etc.. just draw a bunch of png images.

 public class GameCourt extends JPanel {

 public GameCourt(JLabel status) {

 //     setOpaque(false);    
    setBackground(new Color(0,0,0,0));
 // Game constants
public static final int COURT_WIDTH = 1275;
public static final int COURT_HEIGHT = 765;
}

/**
 * (Re-)set the game to its initial state.
 */
public void reset() {
    playing = true;
    status.setText("Running...");

    // Make sure that this component has the keyboard focus
    requestFocusInWindow();
}

/**
 * This method is called every time the timer defined in the constructor
 * triggers.
 */
private void tick() {
    if (playing) {
        repaint();
    }
}
@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    m.drawMaze(g);
    player.draw(g);
    coins.drawCoins(g);
}

@Override
public Dimension getPreferredSize() {
    return new Dimension(COURT_WIDTH, COURT_HEIGHT);
}
}

Here is the JLayeredPanel code (also slightly simplified):

public class LayeredGameCourt extends JLayeredPane {

package Game;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class LayeredGameCourt extends JLayeredPane {


    private GameCourt court;
    public LayeredGameCourt()    {

        setPreferredSize(new Dimension(GameCourt.COURT_WIDTH, GameCourt.COURT_HEIGHT+90));
        setLayout(new BorderLayout());

        final JBackgroundPanel background = new JBackgroundPanel();
        add(background,0);
        background.setBounds(0,0,GameCourt.COURT_WIDTH,GameCourt.COURT_HEIGHT+90);

        // Status panel
        final JLabel status = new JLabel("Running...");

        // Main playing area
        final GameCourt court = new GameCourt(status);
        this.court=court;
        add(court, 1);
        court.setBounds(0,90,GameCourt.COURT_WIDTH,GameCourt.COURT_HEIGHT);

        // Reset button
        final JPanel control_panel = new JPanel();
        add(control_panel, 1);


        final JButton reset = new JButton("Reset");
        reset.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                court.reset();
            }
        });
        control_panel.add(status);
        control_panel.add(reset);
        // Start game
        court.reset();
    }

    public void requestFocusForGC(){
        court.requestFocusInWindow();
    }

    }

And finally, the (useless) backgroundPanel code, if it helps:

@SuppressWarnings("serial")
public class JBackgroundPanel extends JPanel {

    private BufferedImage background;
    public JBackgroundPanel() {
        try {
            if (background == null) {
                background = ImageIO.read(new File("background.png"));
            }
        } catch (IOException e) {
            System.out.println("Internal Error:" + e.getMessage());
        } 
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(background, 0, 0,null);  
        System.out.println("attempting to paint");
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(GameCourt.COURT_WIDTH, GameCourt.COURT_HEIGHT+90);
    }
}
JoeVictor
  • 1,806
  • 1
  • 17
  • 38

1 Answers1

0

Never mind, got it to work!

For other people who might be having the same problem. Here is how my thought process went.

Why can't I do add(Background, new Integer(0))?

Maybe it's because background isn't a component? Nope. Looked over java docs, realized they didn't set the layout type. Maybe my .add calls the the .add for the BorderLayout i added, that's why it fails.

So I removed it and it worked!!!

All I needed to do was to freakin comment out one line that I for some godammn reason decided needed to be there.

But it works!!!!

For clarification: This is the line I removed:

setLayout(new BorderLayout());

Thanks for (if) anyone who was trying to help!

JoeVictor
  • 1,806
  • 1
  • 17
  • 38
  • As described in [How to use layered panes](https://docs.oracle.com/javase/tutorial/uiswing/components/layeredpane.html) - *"When adding a component to a layered pane you specify the layer with an Integer. When using setLayer to change a component's layer, you use an int. You might think that if you use an int instead of an Integer with the add method, the compiler would complain or your program would throw an illegal argument exception. But the compiler says nothing, which results in a common layered pane problem."* – MadProgrammer Dec 07 '15 at 09:44
  • By default `JLayeredPane` doesn't have a default layout manager, you can use them, but then you are restricted by the way in which that layout manager works, for example `BorderLayout` will only manage a single component at any of the 5 available slots, if you add more components to the same position, only the last one will be managed – MadProgrammer Dec 07 '15 at 09:46
  • Yeah that's actually why I had trouble focusing too I think, Thanks! – JoeVictor Dec 07 '15 at 23:53