Search code examples
javaswingjframepaint

Transperent background in JFrame bug


I am making a simple Java program. Now it just makes an 8x8 checkers field. But when start my program background of my JFrame like makes a photo of my screen and it doesn't change. However, I set it to be white. Is it a problem with the code or something else is wrong?

I set the background to be white and didn't set it at all. Neither helped.

package mainpackage;

import com.sun.prism.paint.*;

import javax.swing.*;
import java.awt.*;
import java.awt.Color;
import java.io.File;

class Field extends JFrame {

    Field() //little constructor with no arguments
    {
        this(800, 800);
    }

    Field(int a, int b) //the most big constructor
    {
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setBackground(Color.white);
        setLayout(new FlowLayout());
        setResizable(false);

        setSize(a, b);
    }

    void makeVisible() //making frame visible
    {
        setVisible(true);
    }

    public void makeInvisible() //making frame invisible
    {
        setVisible(false);
    }

    public void paint(Graphics g) //painting the board
    {
        for (int y = 0; y < 10; y++) {
            for (int x = 0; x < 10; x++) {

                g.setColor(getCurrentColor(x,y)); // get and set color of current square
                {
                    if (x % 2 == 0) // if x even
                    {
                        if (y % 2 == 0) {
                            g.setColor(Color.lightGray); // if x even y even make gray
                        } else {
                            g.setColor(Color.pink); // if x even and y odd make pink
                        }
                    } else { // if odd even
                        if (y % 2 == 0) {
                            g.setColor(Color.pink); // if x odd and y even make pink
                        } else {
                            g.setColor(Color.lightGray); // if x odd and y odd make gray
                        }
                    }
                }
                if(x>0&&x<9&&y>0&&y<9) { // only if 0 < x < 9 and 0 < y < 9
                    g.fillRect(50 + 60 * x, 50 + 60 * y, 60, 60); // fill current rectangle
                }
                else if(y==0&&x>0&&x<9)
                {

                    g.setColor(Color.black);
                    g.drawString(Integer.toString(x),50 + 60 * x, 50 + 60 * y);
                }
              /*  if (y == 2&& x== 1) {
                   *//* JLabel label = new JLabel();
                    label.setLocation(x*60, y*60);
                    label.setSize(60, 60);
                    label.setLayout(new GridBagLayout());
                    label.setIcon(new ImageIcon("C:/Users/Asus/Desktop/My Work/checkers/res/images/checkerimage.png"));
                    add(label);*//*
                }*/
            }
        }

    }
    private Color getCurrentColor(int x, int y) //set the color of current square
    {
        if (x % 2 == 0) // if x even
        {
            if (y % 2 == 0) {
                return Color.red;
            } else {
                return Color.blue;// if x even and y odd make blue
            }
        } else { // if odd even
            if (y % 2 == 0) {
                return Color.blue; // if x odd and y even make blue
            } else {
                return Color.red; // if x odd and y odd make red
            }
        }
    }

}

package mainpackage;

public class MainClass {

    public static void main(String[] args) throws InterruptedException {
        Field f1 = new Field();
        f1.makeVisible();

    }
}

Picture of the programm

The second picture


Solution

  • Start by have a read through Painting in AWT and Swing and Performing Custom Painting for a better understanding of how painting works in Swing and how you should work with it.

    Two basic issues:

    1. Overriding paint of JFrame
    2. Breaking the paint chain (failing to call the paint method's super method)

    JFrame is a composite component, that is, it has a number of components already added it that makes up its functionality, which can interfere with the what ever is painted through paint.

    Lots of stuff here

    Painting is a complex process, involving a number of steps, delegated through a series of sub methods. Unless you want to take over ALL the responsibility, you should call super.paintXxx before you perform any custom painting.

    So, what's the answer? Two fold...

    • User JPanel instead of a JFrame as a bases for your component
    • Override paintComponent instead of paint (and call super.paintComponent before you do any custom painting)

    For example...

    import java.awt.*;
    import java.awt.Color;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class Test extends JFrame {
    
        public static void main(String[] args) {
            new Test();
        }
    
        public Test() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.getContentPane().setBackground(Color.RED);
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new Field());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class Field extends JPanel {
    
            public Field() {
                setOpaque(false);
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(800, 600);
            }
    
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                for (int y = 0; y < 10; y++) {
                    for (int x = 0; x < 10; x++) {
    
                        g2d.setColor(getCurrentColor(x, y)); // get and set color of current square
                        {
                            if (x % 2 == 0) // if x even
                            {
                                if (y % 2 == 0) {
                                    g2d.setColor(Color.lightGray); // if x even y even make gray
                                } else {
                                    g2d.setColor(Color.pink); // if x even and y odd make pink
                                }
                            } else { // if odd even
                                if (y % 2 == 0) {
                                    g2d.setColor(Color.pink); // if x odd and y even make pink
                                } else {
                                    g2d.setColor(Color.lightGray); // if x odd and y odd make gray
                                }
                            }
                        }
                        if (x > 0 && x < 9 && y > 0 && y < 9) { // only if 0 < x < 9 and 0 < y < 9
                            g2d.fillRect(50 + 60 * x, 50 + 60 * y, 60, 60); // fill current rectangle
                        } else if (y == 0 && x > 0 && x < 9) {
    
                            g2d.setColor(Color.black);
                            g2d.drawString(Integer.toString(x), 50 + 60 * x, 50 + 60 * y);
                        }
                        /*  if (y == 2&& x== 1) {
                         *//* JLabel label = new JLabel();
                                            label.setLocation(x*60, y*60);
                                            label.setSize(60, 60);
                                            label.setLayout(new GridBagLayout());
                                            label.setIcon(new ImageIcon("C:/Users/Asus/Desktop/My Work/checkers/res/images/checkerimage.png"));
                                            add(label);*//*
                                    }*/
                    }
                }
                g2d.dispose();
            }
    
            private Color getCurrentColor(int x, int y) //set the color of current square
            {
                if (x % 2 == 0) // if x even
                {
                    if (y % 2 == 0) {
                        return Color.red;
                    } else {
                        return Color.blue;// if x even and y odd make blue
                    }
                } else { // if odd even
                    if (y % 2 == 0) {
                        return Color.blue; // if x odd and y even make blue
                    } else {
                        return Color.red; // if x odd and y odd make red
                    }
                }
            }
    
        }
    }
    

    If you really want a transparent window, then you should look at How to Create Translucent and Shaped Windows