我遇到了一个非常奇怪的问题,在Windows上有一个非常大的Java程序。我写了一个小测试程序来重现这个问题。
在Windows打开UAC提示叠加后,自定义透明的JDialog将重新绘制为全白色。
给出以下简单的测试类:
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
public class DialogTests extends JDialog {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
EventQueue.invokeLater(() -> {
new DialogTests().setVisible(true);
});
}
public DialogTests() {
this.setAutoRequestFocus(false);
this.setUndecorated(true);
this.setAlwaysOnTop(true);
this.setFocusableWindowState(true);
this.setBackground(new Color(0,255,255,0));
JPanel contentPane = new JPanel();
contentPane.setBackground(new Color(0,0,0,200));
setContentPane(contentPane);
setBounds(200, 200, 500, 500);
JLabel label = new JLabel("this is just to see something!");
label.setForeground(new Color(255,0,0,255));
contentPane.add(label);
JButton button1 = new JButton("test button 1");
button1.setBackground(new Color(0,0,0,0));
contentPane.add(button1);
JButton button2 = new JButton("test button 2");
button2.setBackground(new Color(0,0,0,0));
contentPane.add(button2);
}
}
以下一系列操作能够为我重现这个问题:
答案 0 :(得分:0)
如果你不必,不要在Color中使用不透明度。这打破了关于不透明的绘画合同,并可能导致绘画伪影。有关可能导致的问题,请参阅Background With Transparency。
使用255时,组件是不透明的。使用0时,组件是不透明的。所以只需使用:
component.setOpaque(true or false);
在框架或对话框上使用透明度时,可以直接设置opactity。尝试使用:
this.setBackground(new Color(0,255,255)); // play with this color
this.setOpacity(0.75f); // play with this opacity.
...
//contentPane.setBackground(new Color(0,0,0,200));
contentPane.setOpaque(false);
答案 1 :(得分:0)
我自己找到了一个解决方法,涉及使用JNA library。似乎通过使用WindowUtils.setWindowTransparent()
,渲染模式的改变方式不再导致错误。
以下扩充代码应该可以正常工作:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import com.sun.jna.platform.WindowUtils;
public class DialogTests extends JDialog {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
try {
System.setProperty("sun.java2d.noddraw", "true");
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
EventQueue.invokeLater(() -> {
new DialogTests().setVisible(true);
});
}
public DialogTests() {
this.setAutoRequestFocus(false);
this.setUndecorated(true);
this.setAlwaysOnTop(true);
this.setFocusableWindowState(true);
this.setBackground(new Color(0,255,255,0));
WindowUtils.setWindowTransparent(this, true);
JPanel contentPane = new JPanel();
contentPane.setBackground(new Color(0,0,0,200));
contentPane.setPreferredSize(new Dimension(200,200));
setContentPane(contentPane);
setBounds(200, 200, 500, 500);
JLabel label = new JLabel("this is just to see something!");
label.setForeground(new Color(255,0,0,255));
contentPane.add(label);
JButton button1 = new JButton("test button 1");
button1.setBackground(new Color(0,0,0,0));
contentPane.add(button1);
JButton button2 = new JButton("test button 2");
button2.setBackground(new Color(0,0,0,0));
contentPane.add(button2);
}
}
唯一需要考虑的事项:
System.setProperty("sun.java2d.noddraw", "true");
WindowUtils.setWindowTransparent(this, true);
之前设置,之后无法更改