我在Swing中使用透明背景时遇到问题。 由于挥杆没有重新改变区域,因此产生了大量的人工制品。
据我所知,有两种开箱即用的方式可以使用透明背景:
问题:背景的透明部分永远不会刷新 - >假象。
问题:根本没有绘制背景。
我做什么不想做:
我在Win7 x64上运行
Aaaand在这里是我的SSCCEEE:
使用invokeLater更新1:init(仍然无效)
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看起来挥杆无法画出透明的背景。 但是,我还不清楚为什么,我搜索了负责绘制组件背景的代码片段,并在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);
}
我只是检查组件是否不透明时是否设置了背景。 这个简单的添加将允许我们在秋千中使用透明背景。 至少我不知道为什么不应该这样做。
答案 0 :(得分:2)
通过使用透明背景,您将破坏Swings绘画规则。基本上,当组件不透明时,您承诺绘制组件的背景。但由于背景是透明的,因此无需绘画。
查看Backgrounds With Transparency以获取更多信息和一些简单的解决方案。
答案 1 :(得分:1)
您应该尊重Swing的线程策略,并在GUI线程上初始化GUI:
SwingUtilities.invokeLater(() -> new OpacityBug());
我无法判断这是否只是为了纠正你身边的行为,但它已经完成了我的(OS X)。
答案 2 :(得分:1)
我不能强调这一点,我看到很多人没有这样做,而确保Swing的正确行为至关重要;所有GUI实例必须在EDT(事件调度线程)上运行
请阅读以下文章并调整您的代码并报告效果。
https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html
答案 3 :(得分:0)
您应该在有问题的组件上使用setOpaque(false)
,并对所有父母执行相同操作!
例如,如果您有JList
' jList'在JScrollPane
' scrollPane'内,整个内容位于JPanel
' jPanel'内,您应该使用:
jList.setOpaque(false);
scrollPane.setOpaque(false);
scrollPane.getViewport().setOpaque(false);
jPanel.setOpaque(false);
是的,如果您有JScrollPane
,则应将其视口的不透明度设置为false。
这将防止具有透明背景的组件上的绘画问题。