Colourfit
Colourfit

Reputation: 367

Why is this JPanel not visible?

I have a custom JPanel, behind another custom JPanel, In a JLayeredPane. I only want to draw the background JPanel once. As it does not change. This would save system resources. How do I do this successfully?

I know if I were to allow the background JPanel to be drawn repeatedly just like the foreground JPanel, it would be seen. But that disregards my goal. Which is to only draw it once.

To re-iterate. How do I draw the background JPanel once, and draw the foreground JPanel reccursively, while both of the JPanel's being seen in a JLayeredPane, Where the background JPanel is behind the foreground JPanel

This is my current attempt. This does not work. The problem with this code is that the background JPanel is simply not visible`

That question is not a duplicate as people are adressing unrelated issues. I have now made this question address the issue I am wanting to solve. If it helps you to solve my issue. Then the link to the question is here. question. This question also has a bad, meaningless answer. Which I even still tried out and dosent work.

import javax.swing.*;

import java.awt.*;
import java.awt.event.*;

public class Main extends JLayeredPane {
    static JFrame frame;
    static Main main;
    static Dimension screenSize;
    public Main() {     
        JPanel backPanel = new BackPanel();
        JPanel frontPanel = new FrontPanel();
        add(backPanel, new Integer(7));
        add(frontPanel, new Integer(8));

        new Thread(() -> {
            while (true){
                repaint();
            }
        }).start();

        RepaintManager.currentManager(backPanel).markCompletelyClean(backPanel);

    }

    public static void main(String[] args) {
        screenSize = Toolkit.getDefaultToolkit().getScreenSize();

        frame = new JFrame("Game"); // Just use the constructor

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        main = new Main();
        frame.add(main, BorderLayout.CENTER);

        frame.pack();
        frame.setSize(screenSize);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);



    }
    public class BackPanel extends JPanel{
        public boolean drawn = false;
        public BackPanel(){
            setVisible(true);
            setOpaque(false);
            setSize(screenSize);
            JLabel test1 = new JLabel("Test1");
            JLabel test2 = new JLabel("Test2");
            add(test1);
            add(test2);
        }
        @Override
        public void paintComponent(Graphics g){
            if (!drawn){
                super.paintComponent(g);
                g.setColor(Color.red);
                g.fillRect(0, 0, screenSize.width, 200);
                System.out.println("Reccursion");
                drawn = true;
            }           
        }
    }
    public class FrontPanel extends JPanel{

        public FrontPanel(){
            setVisible(true);
            setOpaque(false);
            setSize(screenSize);
            JLabel test = new JLabel("Test");
            add(test);
        }
        @Override
        public void paintComponent(Graphics g){
            super.paintComponent(g);
            g.setColor(Color.blue);
            g.fillRect(0+screenSize.width/2, 0, screenSize.width/4, 300);
        }
    }
}

Upvotes: 0

Views: 119

Answers (1)

camickr
camickr

Reputation: 324088

First of all some general comments. You should not:

  1. extend JLayeredPane.
  2. use static variables
  3. use a while true loop

It doesn't matter if this is an MCVE. An MCVE should use proper structure otherwise we might assume you are making the above mistakes in your real code.

In your while loop you use:

repaint();

Well, your code extends a JLayeredPane so all the layers of the layered pane are painted.

If you only want to repaint one panel then invoke repaint() only on that panel. However this can cause problems because you need to make sure the background is cleared before you do any painting on it which is why the background also needs to be painted.

If you don't want to repaint the entire background then you need to be specific about which areas need repainting. Check out the section from the Swing tutorial on Custom Painting that shows how you can optimize what is painted. Notice how the moveSquare(...) method invokes repaint() twice on two different areas. This will cause a smaller background area to be repainted.

Upvotes: 2

Related Questions