0

I have a weird problem. Trying to create a transparent window with java swing works on Java 1.7, but fails on Java 1.8. Unfortunately, I can't figure out how to solve it there. In fact Graphics.clearRect() works for 1.7, whereas it doesn't for 1.8. I've tried to implement https://tips4java.wordpress.com/2009/05/31/backgrounds-with-transparency/, still no success. Here's the code for recreation:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Testpanel
{
    private JLabel Testlabel;
    private JFrame Hintergrundfenster;
    private Bewegungspanel meinBewegungspanel;
    public class Bewegungspanel extends JPanel
    {
        @Override
        protected void paintComponent(Graphics Grafik)
        {
            Grafik.clearRect(0,0,getWidth(), getHeight());
        }
        public Bewegungspanel()
        {
            addMouseListener(new MouseAdapter()                             
            {
                public void mouseEntered(MouseEvent Ereignis)
                {
                    Testlabel.setText("Hi");

                }
                public void mouseExited(MouseEvent Ereignis)
                {
                    Testlabel.setText("Bye");
                }
            });
        }
    }
    public static void main(String args[])
    {
        Testpanel meinTestpanel = new Testpanel();
    }
    public Testpanel()
    {
        Testlabel = new JLabel("Hello")
        /*{
            @Override
            protected void paintComponent(Graphics Grafik)
            {
                Grafik.clearRect(0,0,0,0);                              
            }
        }*/;
        Hintergrundfenster = new JFrame();
        Hintergrundfenster.setUndecorated(true);
        Hintergrundfenster.setSize(100,100);
        meinBewegungspanel = new Bewegungspanel();
        meinBewegungspanel.setLayout(new GridLayout(2,2));
        meinBewegungspanel.add(Testlabel);
        meinBewegungspanel.setBackground(new Color(0,0,0,140));
        Hintergrundfenster.setBackground(new Color(0,0,0,0));
        Hintergrundfenster.add(meinBewegungspanel);
        Hintergrundfenster.setVisible(true);
    }
}

When hovering the mouse over the label, its text changes. The new data is drawn over the old one only on 1.8, resulting in ugly artefacts:

This is the version 1.8 result:

Screenshot of version 1.8

With java 1.7:

Screenshot of version 1.7

I'd appreciate any ideas to solve the problem. Thanks in advance.

Ansharja
  • 1,237
  • 1
  • 14
  • 37
  • Side note: as per the Java code conventions fields, variables _and_ parameters should start with a lower case characters (this is meant to make it easier to distinguish between classes and variables), thus things like `mouseEntered(MouseEvent Ereignis)` or `JLabel Testlabel` could eventually lead to confusion. – Thomas Dec 01 '17 at 14:55
  • Your link is from 2009, so it was not made for java 8. It might be an update that have change the behavior, also you don't call the `super.paintComponent` in your `Bewegungspanel.paintComponent` – AxelH Dec 01 '17 at 14:57
  • My code actually doesn't use the linked approach. I just mentioned it to point out that I tried several ways to solve that issue. – TheEndIsWhereWeBegin Dec 01 '17 at 15:01
  • Have you tried this? https://stackoverflow.com/questions/14927980/how-to-make-a-transparent-jframe-but-keep-everything-else-the-same – Federico José Sorenson Dec 01 '17 at 15:06
  • Federico. I tried, but the outcome is not what I'm looking for. – TheEndIsWhereWeBegin Dec 01 '17 at 15:17
  • How is that link not what you are looking for? The example show how to do transparency on a frame which is what you asked for. Setting the opacity is how you make a frame transparent. And the "backgrounds with transparency" link shows how to make components transparent. The code you posted does not resemble the code found in either link. – camickr Dec 01 '17 at 15:27
  • I tried to use the AlphaContainer class as well as to implement different paintComponent methods as suggested in those links, but I always failed. – TheEndIsWhereWeBegin Dec 01 '17 at 17:43
  • Federico: I eventually tried this, yet the image is transparent, even though I just copy-and-pasted the code. https://i.imgur.com/BFj975L.png – TheEndIsWhereWeBegin Dec 04 '17 at 22:02

1 Answers1

0

Oddly enough, I just found out that inserting a single line (see commented code) solves the problem at least for java 9, the successor. The program thus works for 7 and 9. So this appears to be a java 1.8 bug, as I had initially expected. I will quit support for 1.8 then.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Testpanel
{
    private JLabel Testlabel;
    private JFrame Hintergrundfenster;
    private Bewegungspanel meinBewegungspanel;
    public class Bewegungspanel extends JPanel
    {
        @Override
        protected void paintComponent(Graphics Grafik)
        {
            Grafik.clearRect(0,0,getWidth(), getHeight());
        }
        public Bewegungspanel()
        {
            setOpaque(false);    // This line does the trick for java 1.9
            addMouseListener(new MouseAdapter()                             
            {
                public void mouseEntered(MouseEvent Ereignis)
                {
                    Testlabel.setText("Hi");

                }
                public void mouseExited(MouseEvent Ereignis)
                {
                    Testlabel.setText("Bye");
                }
            });
        }
    }
    public static void main(String args[])
    {
        Testpanel meinTestpanel = new Testpanel();
    }
    public Testpanel()
    {
        Testlabel = new JLabel("Hello")
        /*{
            @Override
            protected void paintComponent(Graphics Grafik)
            {
                Grafik.clearRect(0,0,0,0);                              
            }
        }*/;
        Hintergrundfenster = new JFrame();
        Hintergrundfenster.setUndecorated(true);
        Hintergrundfenster.setSize(100,100);
        meinBewegungspanel = new Bewegungspanel();
        meinBewegungspanel.setLayout(new GridLayout(2,2));
        meinBewegungspanel.add(Testlabel);
        meinBewegungspanel.setBackground(new Color(0,0,0,140));
        Hintergrundfenster.setBackground(new Color(0,0,0,0));
        Hintergrundfenster.add(meinBewegungspanel);
        Hintergrundfenster.setVisible(true);
    }
}
  • More here: "If you do not honor the [_opaque property_](http://www.oracle.com/technetwork/java/painting-140037.html#props) you will likely see visual artifacts."—[`paintComponent()`](http://docs.oracle.com/javase/8/docs/api/javax/swing/JComponent.html#paintComponent-java.awt.Graphics-) – trashgod Dec 01 '17 at 23:18
  • Problem is, Java 1.8 obviously does not care about it being set to false. – TheEndIsWhereWeBegin Dec 03 '17 at 03:26
  • More specifically, the extant Look&Feel controls the setting. See also [*Initial Threads*](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html), which has become more critical in recent updates. – trashgod Dec 04 '17 at 02:11