Java 透明背景JFrame Linux上的动画

Java 透明背景JFrame Linux上的动画,java,linux,background,jframe,transparent,Java,Linux,Background,Jframe,Transparent,我想为一个帧(或JFrame)创建一个完全透明的背景,并让它显示一个透明的动画。我设法让它在Windows7x64中工作,但在我的Linux(LubuntuX64 15.04)上没有运行相同的代码 下面的代码显示了我试图实现的目标——只需复制并粘贴它。我只想让小矩形在屏幕上移动而不留下痕迹 static int a = 0; public static void main(String[] args) { JFrame f = new JFrame(); f.setUnd

我想为一个帧(或JFrame)创建一个完全透明的背景,并让它显示一个透明的动画。我设法让它在Windows7x64中工作,但在我的Linux(LubuntuX64 15.04)上没有运行相同的代码

下面的代码显示了我试图实现的目标——只需复制并粘贴它。我只想让小矩形在屏幕上移动而不留下痕迹

static int  a   = 0;

public static void main(String[] args) {
    JFrame f = new JFrame();
    f.setUndecorated(true);
    f.setBackground(new Color(0, 0, 0, 0));
    f.setVisible(true);
    f.setSize(512, 512);
    f.add(new JPanel() {
        @Override
        public void paintComponent(Graphics gr) {
            Graphics2D g = (Graphics2D)gr;
            g.setBackground(new Color(0, 0, 0, 0));
            g.clearRect(0, 0, 512, 512);
            g.drawRect(a, a++, 2, 2);
        }
    });

    while(true) {
        try {
            Thread.sleep(30);
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
        f.repaint();
    }
}
我想要实现的目标(如Windows所示)以及我通过Lubuntu 15.04获得的目标:

我只想看到小正方形移动,就像Windows7上显示的那样——我不想看到痕迹

请不要给我Oracle透明度和窗口文档的链接——我已经看了三遍了

我所尝试的:

  • Graphics2D的透明空间的“copyArea()”。(这曾经很有效,但现在不再有效)
  • 玻璃板
  • 字母组合
  • setPaint()

请先测试一下你的想法/代码。我已经尝试过很多“这应该有用”的东西,但似乎并没有。。。非常感谢所有帮助。

如果我们扩展JFrame,将“未装饰”设置为true,并使用覆盖绘制,我们可以制作一个透明的JFrame

试试这个

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class TestTransparentFrame {

private class PaintPanel extends JPanel {
    private List<Point> points = new ArrayList<Point>();

    public PaintPanel() {
        setOpaque(false);
        MouseAdapter adapter = new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                points.clear();
                repaint();
            }

            @Override
            public void mouseMoved(MouseEvent e) {
                points.add(e.getPoint());
                repaint();
            }
        };
        addMouseListener(adapter);
        addMouseMotionListener(adapter);
        setBorder(BorderFactory.createLineBorder(Color.GREEN));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (points.size() > 1) {
            g.setColor(Color.RED);
            Point p1 = points.get(0);

            for (int i = 1; i < points.size(); i++) {
                Point p2 = points.get(i);
                g.drawLine(p1.x, p1.y, p2.x, p2.y);
                p1 = p2;
            }
        }
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(700, 500);
    }
}

protected void createAndShowGUI() throws MalformedURLException, IOException {
    JFrame frame = new JFrame("Test transparent painting");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setUndecorated(true);
    frame.setBackground(new Color(0, 0, 0, 50));
    frame.add(new PaintPanel());
    frame.pack();
    frame.setVisible(true);
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            try {
                new TestTransparentFrame().createAndShowGUI();
            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    });

}

}
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Graphics;
导入java.awt.Point;
导入java.awt.event.MouseAdapter;
导入java.awt.event.MouseEvent;
导入java.io.IOException;
导入java.net.MalformedURLException;
导入java.util.ArrayList;
导入java.util.List;
导入javax.swing.BorderFactory;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.SwingUtilities;
公共类TestTransparentFrame{
私有类PaintPanel扩展了JPanel{
私有列表点=新的ArrayList();
公共绘画小组(){
设置不透明(假);
MouseAdapter适配器=新的MouseAdapter(){
@凌驾
公共无效mouseClicked(MouseEvent e){
点。清除();
重新油漆();
}
@凌驾
public void mouseMoved(MouseEvent e){
添加(例如getPoint());
重新油漆();
}
};
addMouseListener(适配器);
addMouseMotionListener(适配器);
setboorder(BorderFactory.createLineBorder(Color.GREEN));
}
@凌驾
受保护组件(图形g){
超级组件(g);
如果(points.size()>1){
g、 setColor(Color.RED);
点p1=点。获取(0);
对于(int i=1;i
作为参考,这里有一个最小的、适合跨平台测试的方法。注意

  • 在一些平台上,例如Ubuntu,完全透明的背景不被视为是透明的;一个小的、非零的alpha值是一个典型的解决方案

  • Swing GUI对象应仅在上构造和操作

  • 使用在事件调度线程上运行的来调整动画的速度

  • 当您真正想覆盖时,不要使用
    setPreferredSize()


基本上,这个问题与操作系统有关。适用于Windows的东西不适用于Linux,反之亦然

出于某些原因,Linux在设置缓冲策略时只允许动画每像素透明度。但是,此解决方案在Windows上失败。因此,我提出了以下代码,根据操作系统选择正确的算法:

static int a = 0;

public static void main(String[] args) {
    JFrame f = new JFrame();
    JPanel p = new JPanel() {
        @Override
        public void paintComponent(Graphics g) {
            Graphics2D g2d = (Graphics2D) g;
            g2d.setBackground(new Color(255, 255, 255, 0));
            g2d.clearRect(0, 0, f.getWidth(), f.getHeight());
            g2d.drawRect(a, a++, 2, 2);
        }
    };
    f.add(p);
    f.setUndecorated(true);
    f.setBackground(new Color(255, 255, 255, 0));
    f.setSize(512, 512);
    f.setVisible(true);
    f.createBufferStrategy(2);

    BufferStrategy bs = f.getBufferStrategy();
    while (true) {
        try {
            Thread.sleep(33);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (System.getProperty("os.name").contains("indows ")) {
            p.repaint();
        } else {
            Graphics g = null;
            do {
                try {
                    g = bs.getDrawGraphics();
                    p.update(g);
                } finally {
                    g.dispose();
                }
                bs.show();
            } while (bs.contentsLost());
            Toolkit.getDefaultToolkit().sync();
        }
    }
}
此代码适用于我的Windows 7 x64和Lubuntu 15.04 x64。请自己尝试一下这个代码,看看它是否适合你。我自己没有Mac电脑,所以如果有人能帮我测试一下,我将非常感激。如果它对任何人都不起作用,请让我知道

这是你应该看到的:


谢谢回复,但我已经试过了。如果你可以编辑你的答案并粘贴工作代码,这将是伟大的。Thx为张贴你的代码,但这个特殊的例子不适用于我的问题。我希望移动鼠标时线条/轨迹消失。问题是JFrame在重新绘制JPanel之前没有清除其屏幕内容。换言之,JPanel一直在自我拉拢。。。这就是我面临的问题,但感谢您的帮助:)对于其他平台/版本,欢迎使用。谢谢您的回复,但这并不能回答我的问题。我知道如何创建一个透明的框架,我的示例代码已经完成了。我想知道如何创建动画。我刚刚测试了我在Windows机器上发布的代码,我的代码似乎运行良好,因此出于某种原因,它不想在我的Linux上工作。不确定这是Linux、Ubuntu还是LXDE的问题…@Roland:啊,我误解了你的例子,它似乎在修改
a<
static int a = 0;

public static void main(String[] args) {
    JFrame f = new JFrame();
    JPanel p = new JPanel() {
        @Override
        public void paintComponent(Graphics g) {
            Graphics2D g2d = (Graphics2D) g;
            g2d.setBackground(new Color(255, 255, 255, 0));
            g2d.clearRect(0, 0, f.getWidth(), f.getHeight());
            g2d.drawRect(a, a++, 2, 2);
        }
    };
    f.add(p);
    f.setUndecorated(true);
    f.setBackground(new Color(255, 255, 255, 0));
    f.setSize(512, 512);
    f.setVisible(true);
    f.createBufferStrategy(2);

    BufferStrategy bs = f.getBufferStrategy();
    while (true) {
        try {
            Thread.sleep(33);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (System.getProperty("os.name").contains("indows ")) {
            p.repaint();
        } else {
            Graphics g = null;
            do {
                try {
                    g = bs.getDrawGraphics();
                    p.update(g);
                } finally {
                    g.dispose();
                }
                bs.show();
            } while (bs.contentsLost());
            Toolkit.getDefaultToolkit().sync();
        }
    }
}