[英]Swing transparent background not being repainted
我在Swing中使用透明背景时遇到问题。 由于摇摆不重涂变化的区域,因此产生了许多人工制品。
据我所知,有两种现成的使用透明背景的方法:
问题 :背景的透明部分永远不会刷新->伪像。
问题 :根本没有绘制背景。
我不想做的事:
我在Win7 x64上运行
Aaaand这是我的SSCCEEE:
更新1:使用invokeLater初始化(仍然无法使用)
public class OpacityBug {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new OpacityBug();
}
});
}
static final Color transparentBlue = new Color(0f, 1f, 0f, 0.5f);
JFrame frame;
JPanel content;
JTextField txt1;
JTextField txt2;
public OpacityBug() {
initFrame();
initContent();
}
void initFrame() {
frame = new JFrame();
frame.setSize(300, 80);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
}
void initContent() {
content = new JPanel();
content.setDoubleBuffered(true);
content.setBackground(Color.red);
frame.getContentPane().add(content);
txt1 = new JTextField() {
@Override
public void setBorder(Border border) {
super.setBorder(null); //nope border
}
};
txt1.setText("Hi! I am Buggy!");
txt1.setOpaque(true);
txt1.setBackground(transparentBlue);
content.add(txt1);
txt2 = new JTextField() {
@Override
public void setBorder(Border border) {
super.setBorder(null); //nope border
}
};
txt2.setText("And I have no BG!");
txt2.setOpaque(false);
txt2.setBackground(transparentBlue);
content.add(txt2);
content.revalidate();
content.repaint();
}
}
更新2
如您所知,Swing的Swing似乎无法绘制透明背景。 但是我还不清楚为什么,我搜索了负责绘制组件背景的代码,并在ComponentUI.java中找到了以下代码:
public void update(Graphics g, JComponent c) {
if (c.isOpaque()) {
g.setColor(c.getBackground());
g.fillRect(0, 0, c.getWidth(),c.getHeight());
}
paint(g, c);
}
如您所见,它假定如果组件不是不透明的,则不需要重新绘制背景。 我说这是一个非常模糊的假设。
我建议以下实施:
public void update(Graphics g, JComponent c) {
if(c.isOpaque() || (!c.isOpaque() && c.isBackgroundSet())) {
g.setColor(c.getBackground());
g.fillRect(0, 0, c.getWidth(), c.getHeight());
}
paint(g, c);
}
我只是检查组件不透明时是否设置了背景。 这种简单的添加将使我们能够在秋千中使用透明背景。 至少我不知道为什么不应该这样做。
通过使用透明背景,您正在打破Swings绘画规则。 基本上,当组件不透明时,您保证会绘制组件的背景。 但是因为背景是透明的,所以不需要绘画。
请查看“ 透明背景”,以获取更多信息和几个简单的解决方案。
您应该遵守Swing的线程策略,并在GUI线程上初始化GUI:
SwingUtilities.invokeLater(() -> new OpacityBug());
我不能说这是否是纠正您这一方面行为所需要的全部,但它只是在我的OS X上完成的。
我不能对此施加足够的压力,我看到很多人没有这样做,而确保Swing的正确行为至关重要。 所有GUI实例必须在EDT(事件调度线程)上运行
请阅读以下文章并调整您的代码,并报告有关效果。
https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html
您应该在有问题的组件上使用setOpaque(false)
, 并对所有父组件执行相同的操作 !
举例来说,如果你有一个JList
一个内部“JList的JScrollPane
“滚动窗格”,整个事情是一个内部JPanel
“的JPanel”,你应该使用:
jList.setOpaque(false);
scrollPane.setOpaque(false);
scrollPane.getViewport().setOpaque(false);
jPanel.setOpaque(false);
是的,如果您有JScrollPane
,则还应该将其视口的不透明度设置为false。
这样可以防止在具有透明背景的组件上出现绘画问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.