我创造了大量具有半透明度的工作示例,但却发现了另一天,那种看似无关的最小变化使得整个代码“无法正常工作”。我终于设法写了最小的'这种行为的荒谬例子。
'短'摘要:在构造函数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