Swing:动态改变JWindow的透明度

时间:2015-05-27 17:06:37

标签: java swing transparency

我正在尝试用java / swing编写一个能够交替使用JWindow或JFrame的透明度的应用程序。例如:JWindow中显示了一个JLabel。如果用户双击该窗口,它将消失,仅显示JLabel。如果他再次双击它,窗口应该再次出现。

目前,只要窗口消失,图像的旧背景就会停留在同一个地方。当我之后改变窗口的大小时,新的部分是不可见的(因为整个JWindow应该是)。看起来新背景的完整透明画在旧画面上绘制,因此旧画面保持可见。您可以在pic1 pic2中看到它。灰色框是使用过的JWindow。 pic2中的红色边框显示了JWindow的当前大小,其中包含旧的可见背景和新的不可见部分。

我最终得到了以下代码(由here操纵)

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;


public class TranscluentWindow
{
public float opacity = 1f;
JFrame frame;

public static void main(String[] args)
{
    new TranscluentWindow();
}

public TranscluentWindow()
{
    EventQueue.invokeLater (new Runnable ()
    {
        @Override
        public void run ()
        {
            try
            {
                UIManager.setLookAndFeel (UIManager.getSystemLookAndFeelClassName ());
            } catch (Exception ex)
            {
            }

            frame = new JFrame ();
            frame.setUndecorated (true);
            frame.setAlwaysOnTop (true);
            frame.addMouseListener (new MouseAdapter ()
            {
                @Override
                public void mouseClicked (MouseEvent e)
                {
                    if(e.getClickCount () % 2 == 0)
                    {
                        if(opacity == 1)
                        {
                            opacity = 0;
                            frame.setSize (200,200);
                            JLabel label =new JLabel ("FOOOOO BAAAR2");
                            label.setForeground (Color.red);
                            frame.add (label);
                            frame.invalidate ();
                            frame.repaint ();
                        }
                        else
                            opacity = 1;
                        frame.invalidate ();
                        frame.repaint ();
                        frame.getContentPane ().invalidate ();
                        frame.getContentPane ().repaint ();
                    }
                }
            });
            frame.setBackground (new Color (0, 0, 0, 0));
            frame.setContentPane (new TranslucentPane ());
            frame.add (new JLabel ("FOO BAR"));
            frame.pack ();
            frame.setLocationRelativeTo (null);
            frame.setVisible (true);
        }
    });
}

class TranslucentPane extends JPanel {

    public TranslucentPane() {
        setOpaque (false);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setComposite(AlphaComposite.SrcOver.derive(opacity));
        g2d.setColor(getBackground());
        g2d.fillRect(0, 0, getWidth(), getHeight());

    }

}
}

希望有人知道解决方法!

1 个答案:

答案 0 :(得分:0)

  

目前,只要窗口消失,图像的旧背景就会停留在同一个地方

您正在向BorderLayout的CENTER添加第二个组件。这不会取代第一个组件,因此两个组件都被绘制。

使用label.setIcon(...)

代替替换组件,更简单的解决方案是替换Icon

或者如果您必须更换组件,则需要在添加新组件之前从面板中删除以前的组件。

有关将多个组件添加到BorderLayout的CENTER时会发生什么的更多信息,请参阅:Why does the first panel added to a frame disappear?