Search code examples
javaanimationpaneltransparency

Animation on a Transparent Panel


I want to animate an object on a transparent panel (in this case upperPanel), but once the animated object has been added to the upperPanel, its background is no longer transparent.

The upperPanel is in the bottomPanel. The background of bottomPanel is red, so you can see if upperPanel is transparent.

Code of the Frame:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Frame;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class NewFrame extends JFrame{
    
      public static void main(String args[]){
          JFrame f = new JFrame();
          AnimatedObject a = new AnimatedObject();
          JPanel bottomPanel = new JPanel();
          JPanel upperPanel = new JPanel();
          bottomPanel.setBackground(Color.red);
          bottomPanel.setSize(300, 300);
          bottomPanel.setLayout(new BorderLayout());
          upperPanel.setSize(300, 300);
          upperPanel.setOpaque(false);
          upperPanel.setLayout(new BorderLayout());
          f.add(bottomPanel);
          bottomPanel.add(upperPanel);
          upperPanel.add(a);
          f.setSize(400,400);
          f.setVisible(true);
          f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      }
}

Code of the animated Object:

import javax.swing.JFrame;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;

public class AnimatedObject extends javax.swing.JPanel implements ActionListener{

    private int x = 0;
    private int y = 0;
    private boolean direction = true;
    Timer tm = new Timer(50, this);

    public AnimatedObject() {
        initComponents();
        tm.start();
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(new java.awt.Color(102, 102, 102));
        g.fillRect(x, y, 30, 30);
        System.out.println("Test gesetzt("+x+"|"+y+")");
    }
    
    public void moveForward() {
        x = x + 30;
        repaint();
        System.out.println("(" + x + "|" + y + ")");
    }

    public void moveBackwards() {
        x = x - 30;
        repaint();
        System.out.println("(" + x + "|" + y + ")");
    }

    public void moveDown() {
        y = y + 30;
        repaint();
        System.out.println("(" + x + "|" + y + ")");
    }

    public void moveUp() {
        y = y - 30;
        repaint();
        System.out.println("(" + x + "|" + y + ")");
    }

    public void actionPerformed(ActionEvent e) {
       if (direction){
           moveDown();
       }
       else {
           moveUp();
       }
       if (((y >= 270) && (direction)) || ((y <= 0) && (!direction))) {
        moveForward();
        direction = !direction;
       }
      }
}

Solution

  • Because your panels are using BorderLayouts, this will force the child component to fill the entire available space of the parent, because AnimatedObject is not transparent itself, it's filling the space of it's parent with an opaque fill color.

    You can test this by changing the background color of AnimatedObject

    public AnimatedObject() {
        setBackground(Color.BLUE);
        tm.start();
    }
    

    Blue background

    A simple fix would be to make AnimatedObject transparent as well.

    public AnimatedObject() {
        setOpaque(false);
        tm.start();
    }
    

    Transparent