1

Okay I have a Canvas (I am using this because it can implement BufferedStrategy).

I add my Canvas to my JFrame contentPane and than add HUDPanel ( which is a JPanel consisting of 2 other JPanels - with JProgressBars and JLabels - to show health and chakara bars) to my JFrames glassPane.

All of the components on HUD are opaque.

Now when I add the HUDPanel to my JFrames glassPane with a Canvas as its contentPane the 2 JPanels which hold components are not painted opaque:

enter image description here

But if I add a JPanel instead of Canvas to JFrame contentPane all works fine:

enter image description here

Why is this? and how can I fix it?

Thank you in advance

HUDPanelTest.java

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class HUDPanelTest {

    public HUDPanelTest() {
        initComponents();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new HUDPanelTest();
            }
        });
    }

    private void initComponents() {
        JFrame frame = new JFrame() {
            @Override
            public Dimension getPreferredSize() {//testing only
                return new Dimension(800, 600);
            }
        };
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        HUDPanel hudPanel = new HUDPanel();
        frame.setGlassPane(hudPanel);
        JPanel p = new JPanel() {
            @Override
            protected void paintComponent(Graphics grphcs) {
                super.paintComponent(grphcs);
                grphcs.setColor(Color.yellow);
                grphcs.fillRect(0, 0, getWidth(), getHeight());
            }
        };
        Canvas c = new Canvas() {
            @Override
            public void paint(Graphics grphcs) {//for testing ONLY I actually use a BufferStrategy
                super.paint(grphcs);

                grphcs.setColor(Color.yellow);
                grphcs.fillRect(0, 0, getWidth(), getHeight());
            }
        };

        frame.add(c);
        //frame.add(p);//this works as expected

        frame.pack();
        frame.setVisible(true);
        hudPanel.setVisible(true);

    }
}

HUDPanel.java

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;

public class HUDPanel extends JPanel {

    HUDPanel.HealthPanel healthPanel;
    HUDPanel.ChakaraPanel chakaraPanel;

    public HUDPanel() {
        super(new BorderLayout(), true);
        setOpaque(false);

        healthPanel = new HUDPanel.HealthPanel();
        chakaraPanel = new HUDPanel.ChakaraPanel();

        initComponents();

        setHealthPlayer1(100);
        setHealthPlayer2(100);
        setChakaraPlayer1(0);
        setChakaraPlayer2(0);
        setLabelTextHealthPlayer1("Player 1 (Health):");
        setLabelTextHealthPlayer2("Player 2 (Health):");
        setLabelTextChakaraPlayer1("Player 1 (Chakara):");
        setLabelTextChakaraPlayer2("Player 2 (Chakara):");
    }

    private void initComponents() {
        add(healthPanel, BorderLayout.NORTH);
        add(chakaraPanel, BorderLayout.SOUTH);
    }

    public void setHealthPlayer1(int health) {
        healthPanel.setPlayer1ProgressBarValue(health);
    }

    public void setHealthPlayer2(int health) {
        healthPanel.setPlayer2ProgressBarValue(health);
    }

    public void setChakaraPlayer1(int chakara) {
        chakaraPanel.setPlayer1ProgressBarValue(chakara);
    }

    public void setChakaraPlayer2(int chakara) {
        chakaraPanel.setPlayer2ProgressBarValue(chakara);
    }

    public void setLabelTextHealthPlayer1(String text) {
        healthPanel.setPlayer1LabelText(text);
    }

    public void setLabelTextHealthPlayer2(String text) {
        healthPanel.setPlayer2LabelText(text);
    }

    public void setLabelTextChakaraPlayer1(String text) {
        chakaraPanel.setPlayer1LabelText(text);
    }

    public void setLabelTextChakaraPlayer2(String text) {
        chakaraPanel.setPlayer2LabelText(text);
    }

    private class HealthPanel extends JPanel {

        JProgressBar player1ProgressBar = new JProgressBar();
        JProgressBar player2ProgressBar = new JProgressBar();
        JLabel player1Label = new JLabel();
        JLabel player2Label = new JLabel();

        public HealthPanel() {
            super(new GridBagLayout(), true);
            setOpaque(false);

            initComponents();
        }

        private void initComponents() {
            GridBagConstraints gc = new GridBagConstraints();
            gc.fill = GridBagConstraints.NONE;
            gc.anchor = GridBagConstraints.WEST;
            gc.insets = new Insets(10, 10, 10, 10);
            //or else the anchoring wont work
            gc.weightx = 1;

            //gc.gridx = 0;//does not seem to make a difference
            //gc.gridy = 0;
            add(player1Label, gc);

            //gc.gridx = 1;
            //gc.gridy = 0;
            add(player1ProgressBar, gc);

            gc.anchor = GridBagConstraints.EAST;

            //gc.gridx = 2;
            //gc.gridy = 0;
            add(player2Label, gc);

            //gc.gridx = 3;
            //gc.gridy = 0;
            add(player2ProgressBar, gc);
        }

        public void setPlayer1ProgressBarValue(int val) {
            player1ProgressBar.setValue(val);
        }

        public void setPlayer2ProgressBarValue(int val) {
            player2ProgressBar.setValue(val);
        }

        public void setPlayer2LabelText(String text) {
            player2Label.setText(text);
        }

        public void setPlayer1LabelText(String text) {
            player1Label.setText(text);
        }
    }

    private class ChakaraPanel extends JPanel {

        JProgressBar player1ProgressBar = new JProgressBar();
        JProgressBar player2ProgressBar = new JProgressBar();
        JLabel player1Label = new JLabel();
        JLabel player2Label = new JLabel();

        public ChakaraPanel() {
            super(new GridBagLayout(), true);
            setOpaque(false);

            initComponents();
        }

        private void initComponents() {
            GridBagConstraints gc = new GridBagConstraints();
            gc.fill = GridBagConstraints.NONE;
            gc.anchor = GridBagConstraints.WEST;
            gc.insets = new Insets(10, 10, 10, 10);
            //or else the anchoring wont work
            gc.weightx = 1;
            gc.weighty = 1;

            //gc.gridx = 0;
            //gc.gridy = 0;
            add(player1Label, gc);

            //gc.gridx = 1;
            //gc.gridy = 0;
            add(player1ProgressBar, gc);

            gc.anchor = GridBagConstraints.EAST;

            //gc.gridx = 2;
            //gc.gridy = 0;
            add(player2Label, gc);

            //gc.gridx = 3;
            //gc.gridy = 0;
            add(player2ProgressBar, gc);
        }

        public void setPlayer1ProgressBarValue(int val) {
            player1ProgressBar.setValue(val);
        }

        public void setPlayer2ProgressBarValue(int val) {
            player2ProgressBar.setValue(val);
        }

        public void setPlayer2LabelText(String text) {
            player2Label.setText(text);
        }

        public void setPlayer1LabelText(String text) {
            player1Label.setText(text);
        }
    }
}
Jarrod
  • 9,349
  • 5
  • 58
  • 73
David Kroukamp
  • 36,155
  • 13
  • 81
  • 138

1 Answers1

2
  • GlassPane is lightweight, then is always behind AWT Canvas,

  • this is quite common issue for JLayeredPane, GlassPane and Java and 3D, CAD/CAM, Open GL/Cl, these APIs are based on AWT Containers

  • same issue will be by using JLayer (lightweight container), but there you can to test isLightWe....() for peer from Native OS and/or its resources

mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • +1 thank you very some interesting stuff. So mKorbel to clarify would I use a `JLayeredPane` and add my `Canvas` and *Glasspane* to that? Or how would I go about fixing this problem ( please i would like to maintain using a `Canvas` for `BufferedStrategy`, implementing a `Window` would completely change my applications layout.....) due to the fact it is bad practice for use of multiple Frames – David Kroukamp Nov 15 '12 at 17:55
  • Im never to tried BufferedStrategy, I'm bothering with RepaintManager, I'm againt usage of JLayeredPane too, hard to describe some advice, but Swing Gurus always suggested that Swing containers are better for custom painting, sure there are 3D, CAD/CAM, Open GL/CL and they are required resources came from Native OS, then only usage of AWT container is one and possible way – mKorbel Nov 15 '12 at 18:07
  • Why not the default `BufferStrategy` on `JPanel`? Also, constructors should not invoke overridable methods. – trashgod Nov 15 '12 at 18:58
  • @mKorbel but `BufferedStrategy` works great for games with fixed time step game loops hence why i really cannot change the use of canvas, without sacrificing a great gaming loop.... And restarting from scratch???? There must be some type of way? I thought about Window, but that too would change my entire game layout.... and i dont know if it would work or give similar problems – David Kroukamp Nov 15 '12 at 18:59
  • @trashgod BufferedStrategy is better than JPanel BufferedImage, gives more control ( especially because im creating a sprite game a i need full control of painting etc) see [here](http://www.java-gaming.org/index.php?topic=23945.0) – David Kroukamp Nov 15 '12 at 19:00
  • 2
    @DavidKroukamp: Some instructive contrasting examples are cited [here](http://stackoverflow.com/a/2068517/230513). – trashgod Nov 15 '12 at 19:04
  • @trashgod thank you i will have a look, I really hope I can get this too work or there goes my game !! ( the BufferedStrategy game loop is complex, taking into account frames per second, and even has a method to catch up missed frames if performance drops etc) and I cant see how this will be implemented as flawlessly in JPanel – David Kroukamp Nov 15 '12 at 19:07
  • @DavidKroukamp no idea still is there [paintImmedialtelly()](http://www.javadocexamples.com/java_source/com/memoire/laos/LaosGraphics.java.html) – mKorbel Nov 15 '12 at 20:07
  • @Trashgod thank you solved it b using `JPanel` and repaint only by calling `setIgnoreRepaint(..)` on `JPanel` – David Kroukamp Nov 16 '12 at 16:41
  • hmmm then you decided to use Swing JPanel, I think good sensible choice – mKorbel Nov 16 '12 at 16:46
  • 1
    Ah, I see `setIgnoreRepaint()` is "useful…if page-flipping is used as the buffer strategy." – trashgod Nov 16 '12 at 19:54