[英]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.