Linux上的Java窗口半透明animation闪烁

我正在尝试使用半透明的JFrame在Java中进行animation制作。 我在这里修改了Oracle Java教程中的演示代码。 具体是渐变透明窗口演示。

以下代码在Windows XP SP3(最多8个)和Mac OS X Mountain Lion(甚至大多数 Linux)中都能很好地工作。 Linux中的问题,以及我需要帮助的是animation闪烁。

我使用nVidia驱动程序,Metacity和Compiz运行Ubuntu Linux 12.04 LTS 64bit。 PERPIXEL_TRANSLUCENT报告为真,运行良好。

在下面的代码中是否有我缺less的东西,或者有什么需要改变的Linux端? 我在JPanel上尝试了setDoubleBuffered(true),但是并没有消除闪烁。

请将我的代码更改引用到下面的演示:

import static java.awt.GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT; import java.awt.Color; import java.awt.Dimension; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.GridBagLayout; import java.awt.Paint; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.Timer; public class GradientTranslucentWindowDemo extends JFrame implements ActionListener { private Timer timer = new Timer(100, this); private double percentage = 0.0; private JPanel surface = new JPanel() { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if (g instanceof Graphics2D) { final int R = 0; final int G = 240; final int B = 240; Paint p = new GradientPaint(0.0f, 0.0f, new Color(R, G, B, 0), 0.0f, getHeight(), new Color(R, G, B, 255), false); Graphics2D g2d = (Graphics2D)g; // CHANGE 1 // Clear the previous graphics using a completely transparent fill g2d.setBackground(new Color(0, 0, 0, 0)); g2d.clearRect(0, 0, getWidth(), getHeight()); g2d.setPaint(p); // CHANGE 2 // Only do a gradient fill for the current percentage of the width g2d.fillRect(0, 0, (int)Math.ceil(getWidth() * percentage), getHeight()); } } }; public GradientTranslucentWindowDemo() { super("GradientTranslucentWindow"); setBackground(new Color(0,0,0,0)); setSize(new Dimension(300,200)); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // CHANGE 3 // I thought this might remove the flicker, nope this.surface.setDoubleBuffered(true); // CHANGE 4 // This seems to be required or the g2d.clearRect doesn't do anything this.surface.setOpaque(false); setContentPane(this.surface); setLayout(new GridBagLayout()); add(new JButton("I am a Button")); } // CHANGE 5 // On each tick of the timer increment the percentage until its // more than one and always repaint @Override public void actionPerformed(ActionEvent event) { this.percentage += 0.05; if (this.percentage > 1.0) { this.percentage = 0.0; } this.surface.repaint(); } public static void main(String[] args) { // Determine what the GraphicsDevice can support. GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice gd = ge.getDefaultScreenDevice(); boolean isPerPixelTranslucencySupported = gd.isWindowTranslucencySupported(PERPIXEL_TRANSLUCENT); //If translucent windows aren't supported, exit. if (!isPerPixelTranslucencySupported) { System.out.println( "Per-pixel translucency is not supported"); System.exit(0); } JFrame.setDefaultLookAndFeelDecorated(true); // Create the GUI on the event-dispatching thread SwingUtilities.invokeLater(new Runnable() { @Override public void run() { GradientTranslucentWindowDemo gtw = new GradientTranslucentWindowDemo(); // Display the window. gtw.setVisible(true); // CHANGE 6 // Wait until the window is visible to start the timer gtw.timer.start(); } }); } } 

更新1:删除半透明并select黑色背景修复了闪烁问题。 闪烁是有一个半透明的窗口。 我也注意到,当窗口放大时,闪烁变得更糟。

更新2:this.surface.setOpaque(false); 是什么导致了这个问题。 如果这被注释掉,animation不会闪烁,并且有半透明性。 但是,在animation的每次迭代中,它都会与之前的绘画 (未重新绘制前清除内容)进行混合。 做g2d.setBackground(new Color(0, 0, 0, 0));g2d.clearRect(0, 0, getWidth(), getHeight()); 除非this.surface.setOpaque(false); 被设置。 这几乎就像这条线在Linux上禁用双缓冲。

有一个半透明的窗户一个要求。

Solutions Collecting From Web of "Linux上的Java窗口半透明animation闪烁"