Arhn - архитектура программирования

Мерцание анимации полупрозрачности окна Java в Linux

Я пытаюсь сделать анимацию на Java с полупрозрачным JFrame. Я изменил демонстрационный код из руководств по Oracle Java здесь. В частности, GradientTranslucentWindowDemo.

Следующий код отлично работает в Windows XP SP3 до 8 и Mac OS X Mountain Lion и даже в Linux в основном. Проблема в Linux, и мне нужна помощь, заключается в мерцании анимации.

Я использую Ubuntu Linux 12.04 LTS 64bit с драйверами nVidia, Metacity и Compiz. PERPIXEL_TRANSLUCENT сообщает true и работает хорошо.

Есть ли что-то, чего мне не хватает в следующем коде, или мне нужно что-то изменить на стороне Linux? Я попробовал setDoubleBuffered(true) на JPanel, но мерцание не исчезло.

Пожалуйста, ссылайтесь на мои изменения кода в демо ниже:

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: удаление полупрозрачности и выбор черного фона устраняет проблему мерцания. Мерцание, безусловно, связано с полупрозрачным окном. Я также заметил, что мерцание усиливается по мере увеличения окна.

ОБНОВЛЕНИЕ 2: Строка this.surface.setOpaque(false); является причиной проблемы. Если это закомментировать, анимация не мерцает и появляется полупрозрачность. Однако при каждой итерации анимации она смешивается с предыдущей отрисовкой (содержимое не очищается перед перерисовкой). Выполнение g2d.setBackground(new Color(0, 0, 0, 0)); и g2d.clearRect(0, 0, getWidth(), getHeight()); ничего не дает, если не установлено this.surface.setOpaque(false);. Похоже, что эта строка отключает двойную буферизацию в Linux.

Наличие полупрозрачного окна является требованием.


  • Реализации полупрозрачности на win32, osx и X11 (linux) совершенно разные, поэтому решение проблемы на одной вряд ли каким-либо образом отразится на других. Можете ли вы получить родную программу с полупрозрачностью для выполнения той же или подобной операции без мерцания? Если нет, проблема, скорее всего, в настройках вашего оконного менеджера/менеджера отображения или в самом диспетчере, а не в Java как таковой. 29.03.2013

Новые материалы

Коллекции публикаций по глубокому обучению
Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

Представляем: Pepita
Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

Советы по коду Laravel #2
1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

3 способа решить квадратное уравнение (3-й мой любимый) -
1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

Создание VR-миров с A-Frame
Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

Демистификация рекурсии
КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..