Linux下java translucency的奇怪行为

时间:2018-02-03 14:29:07

标签: java translucency

我创造了大量具有半透明度的工作示例,但却发现了另一天,那种看似无关的最小变化使得整个代码“无法正常工作”。我终于设法写了最小的'这种行为的荒谬例子。

'短'摘要:在构造函数ProblematicTranslucentyInteractiveExample中,您会看到2个变体。两种变体都使用 SAME 方法来创建JFrame。当您在该框架内单击时,它将开始将整个区域划分为4个正方形,并用颜色填充该区域。

变体A显示2个这样的框架,一个没有像素半透明,另一个具有半透明性。两个框架都能完美运作!现在对其进行评论并尝试其他变体。

变体B只显示一帧,启用了半透明的帧。 与变体A相同的创建框架的方法但它不起作用。当我运行它时,alfa混合不正确,并且在无效的alfa混合期间,不同的X位置也会产生不同的图形错误。这有多奇怪?编辑:只是为了强调打击线:在这个例子中,半透明框架的创建只有在我用它创建非透明窗口时才有效。如果我只创建半透明窗口,它就不起作用。

在fedora 26上运行,xfce旋转。使用compton合成器,xfce合成器或没有任何合成器进行测试(好的,半透明在这种情况下不会起作用,但会出现不正确的渲染)。测试了几个Oracle JDK版本,也是OpenJDK版本。所有这些都有相同的结果。

任何想法??

编辑:在Windows上测试时,两种变体都可以工作,但是在Linux上,整个帧始终可见,在Windows上只有最后重新绘制的部分可见。这非常不一致!这是正常的吗?或者我在这里有错误吗?

有问题的代码:

package nomouse.transparencytest;

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

import nomouse.provider.LoggerProvider;
import org.apache.logging.log4j.Logger;

public class ProblematicTranslucentyInteractiveExample {

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

    public ProblematicTranslucentyInteractiveExample() {
        EventQueue.invokeLater(() -> {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                ex.printStackTrace();
            }

            //------ VARIANT A --------
            int rectangleWidth = 800;
            showFrame(0, rectangleWidth, false);
            showFrame(50 + rectangleWidth, rectangleWidth, true);

            //------ VARIANT B --------
//            showFrame(0 , 800, true);
        });
    }

    private void showFrame(int x, int rectangleWidth, boolean withAlfa) {
        JFrame frame = new JFrame("Testing");
        frame.setUndecorated(true);
        frame.setBackground(new Color(0, 0, 0, 0));

        frame.setContentPane(createTestComp(() -> {
            frame.setVisible(false);
            frame.dispose();
        }, withAlfa, rectangleWidth));
        frame.pack();
        frame.setLocation(x,0);
        frame.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                frame.setVisible(false);
                frame.dispose();
            }
        });
        frame.setVisible(true);
    }

    private TestComponent createTestComp(Runnable exit, boolean withAlfa, int rectangleWidth) {
        TestComponent testComponent =
                new TestComponent(LoggerProvider.getLogger(ProblematicTranslucentyInteractiveExample.class), exit, withAlfa);

        testComponent.setPreferredSize(new Dimension(rectangleWidth,rectangleWidth));
        return testComponent;
    }

    public static class TestComponent extends JPanel {

        private final Logger logger;
        private int i = 1;
        private final Color black;
        private final Color red;
        private final Color green;
        private final Color blue;
        private final Color yellow;

        public TestComponent(Logger logger, Runnable exit, boolean withAlfa) {
            this.logger = logger;
            this.setOpaque(false);

            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    switch (e.getButton()) {
                        case MouseEvent.BUTTON1: i++;repaint();break;
                        case MouseEvent.BUTTON3: i=1;repaint();break;
                        case MouseEvent.BUTTON2: exit.run();break;
                    }
                }
            });

            black = withAlfa ? new Color(0, 0, 0, 100) : new Color(0, 0, 0);
            red = withAlfa ? new Color(255, 0, 0, 100) : new Color(255, 0, 0);
            green = withAlfa ? new Color(0, 255, 0, 100) : new Color(0, 255, 0);
            blue = withAlfa ? new Color(0, 0, 255, 100) : new Color(0, 0, 255);
            yellow = withAlfa ? new Color(255, 255, 0, 100) : new Color(255, 255, 0);
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            logger.debug("painting starts.");

            Graphics2D g2d = (Graphics2D) g.create();

//            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
//            g2d.setComposite(AlphaComposite.Src.derive(.25f));

            g2d.setComposite(AlphaComposite.Src);

            int width = getWidth();
            int height = getHeight();
            int halfWidth = width / 2;
            int halfHeight = height / 2;
            int quarterWidth = width / 4;
            int quarterHeight = height / 4;
            int oneEightWidth = width / 8;
            int oneEightHeight = height / 8;

            switch (i) {
                case 1: fillRectangle(g2d, 0, 0, width, height, black);break;

                case 2: fillRectangle(g2d, 0, 0, halfWidth, halfHeight, red);break;
                case 3: fillRectangle(g2d, halfWidth, 0, halfWidth, halfHeight, green);break;
                case 4: fillRectangle(g2d, 0, halfHeight, halfWidth, halfHeight, blue);break;
                case 5: fillRectangle(g2d, halfWidth, halfHeight, halfWidth, halfHeight, yellow);break;

                case 6:
                    fillRectangle(g2d, 0, 0, halfWidth, halfHeight, black);
                    fillRectangle(g2d, 0, 0, quarterWidth, quarterHeight, red);
                    break;
                case 7: fillRectangle(g2d, quarterWidth, 0, quarterWidth, quarterHeight, green);break;
                case 8: fillRectangle(g2d, 0, quarterHeight, quarterWidth, quarterHeight, blue);break;
                case 9: fillRectangle(g2d, quarterWidth, quarterHeight, quarterWidth, quarterHeight, yellow);break;

                case 10:
                    fillRectangle(g2d, 0, 0, quarterWidth, quarterHeight, black);
                    fillRectangle(g2d, 0, 0, oneEightWidth, oneEightHeight, red);
                    break;
                case 11: fillRectangle(g2d, oneEightWidth, 0, oneEightWidth, oneEightHeight, green);break;
                case 12: fillRectangle(g2d, 0, oneEightHeight, oneEightWidth, oneEightHeight, blue);break;
                case 13: fillRectangle(g2d, oneEightWidth, oneEightHeight, oneEightWidth, oneEightHeight, yellow);break;
            }


            g2d.dispose();
            logger.debug("painting done.");

        }

        private void fillRectangle(Graphics2D g, int x, int y, int width, int height, Color color) {
            g.setColor(color);
            logger.debug(String.format("Filling rect: %sx%s-%sx%s with color %s",
                    x, y, width, height, color));
            g.fillRect(x, y, width, height);

            g.setColor(Color.cyan);
            g.setStroke(new BasicStroke(5));
            g.drawRect(x, y, width, height);
        }
    }


}

行为截屏: two frames

one frame

0 个答案:

没有答案