在你阅读之前,这里有一些关于问题的澄清:
- SSCCE 是为 Java 7 设计的。可以使用 sun.*.AWTUtilities 使其适应 Java 6,但它在 Java 6 上的工作方式对我来说并不重要。
- 故障线是[...]
new JDialog(someWindow)
。只需将该行更改为[...]new JDialog()
.
为什么顶层窗口不显示重影?
预期行为:(final JDialog d = new JDialog()
见 SSCCE)
如您所见,右侧窗口具有半透明背景(如预期的那样)。
实际行为:(final JDialog d = new JDialog(f)
见 SSCCE)
在这种情况下,右侧窗口具有不透明的背景。事实上,由于任何原因,需要 3-4 次重新绘制(最容易重现的是在翻转时重新绘制)才能使背景变得完全不透明。
SSCCE:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.synth.ColorType;
import javax.swing.plaf.synth.Region;
import javax.swing.plaf.synth.SynthConstants;
import javax.swing.plaf.synth.SynthContext;
import javax.swing.plaf.synth.SynthLookAndFeel;
import javax.swing.plaf.synth.SynthPainter;
import javax.swing.plaf.synth.SynthStyle;
import javax.swing.plaf.synth.SynthStyleFactory;
public class SynthSSCCE
{
public static void main(String[] args) throws Exception
{
final SynthLookAndFeel laf = new SynthLookAndFeel();
UIManager.setLookAndFeel(laf);
SynthLookAndFeel.setStyleFactory(new StyleFactory());
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
final JFrame f = new JFrame();
{
f.add(new JButton("Works properly"));
f.setUndecorated(true);
f.setBackground(new Color(0, true));
f.setSize(300, 300);
f.setLocation(0, 0);
f.setVisible(true);
}
{
final JDialog d = new JDialog(f);
final JButton btn = new JButton("WTF?");
// uncomment and notice that this has no effect
// btn.setContentAreaFilled(false);
d.add(btn);
d.setUndecorated(true);
d.setBackground(new Color(0, true));
d.setSize(300, 300);
d.setLocation(320, 0);
d.setVisible(true);
}
}
});
}
static class StyleFactory extends SynthStyleFactory
{
private final SynthStyle style = new Style();
@Override
public SynthStyle getStyle(JComponent c, Region id)
{
return style;
}
}
static class Style extends SynthStyle
{
private final SynthPainter painter = new Painter();
@Override
protected Color getColorForState(SynthContext context, ColorType type)
{
if (context.getRegion() == Region.BUTTON && type == ColorType.FOREGROUND)
return Color.GREEN;
return null;
}
@Override
protected Font getFontForState(SynthContext context)
{
return Font.decode("Monospaced-BOLD-30");
}
@Override
public SynthPainter getPainter(SynthContext context)
{
return painter;
}
@Override
public boolean isOpaque(SynthContext context)
{
return false;
}
}
static class Painter extends SynthPainter
{
@Override
public void paintPanelBackground(SynthContext context, Graphics g, int x, int y, int w, int h)
{
final Graphics g2 = g.create();
try
{
g2.setColor(new Color(255, 255, 255, 128));
g2.fillRect(x, y, w, h);
}
finally
{
g2.dispose();
}
}
@Override
public void paintButtonBackground(SynthContext context, Graphics g, int x, int y, int w, int h)
{
final Graphics g2 = g.create();
try
{
if ((context.getComponentState() & SynthConstants.MOUSE_OVER) == SynthConstants.MOUSE_OVER)
g2.setColor(new Color(255, 0, 0, 255));
else
g2.setColor(new Color(0xAA, 0xAA, 0xAA, 255));
g2.fillRoundRect(x, y, w, h, w / 2, h / 2);
}
finally
{
g2.dispose();
}
}
}
}
这些是我的问题...
- 到底是怎么回事?例如,为什么这会表现出忘记调用 super 的自定义绘制非透明组件的行为?
- 为什么它不会发生在 TL windows 上?
- 除了不使用非 TL 窗口之外,最简单的修复方法是什么?