7

在你阅读之前,这里有一些关于问题的澄清:

  1. SSCCE 是为 Java 7 设计的。可以使用 sun.*.AWTUtilities 使其适应 Java 6,但它在 Java 6 上的工作方式对我来说并不重要。
  2. 故障线是[...]new JDialog(someWindow)只需将该行更改[...]new JDialog().

为什么顶层窗口不显示重影?


预期行为:(final JDialog d = new JDialog()见 SSCCE) TL 和非 TL 窗口都具有半透明背景

如您所见,右侧窗口具有半透明背景(如预期的那样)。

实际行为:(final JDialog d = new JDialog(f)见 SSCCE) TL 窗口显示半透明背景,而非 TL 背景即使在单次重绘后也变得不透明

在这种情况下,右侧窗口具有不透明的背景。事实上,由于任何原因,需要 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();
                        }
                }
        }
}

这些是我的问题...

  1. 到底是怎么回事?例如,为什么这会表现出忘记调用 super 的自定义绘制非透明组件的行为?
  2. 为什么它不会发生在 TL windows 上?
  3. 除了不使用非 TL 窗口之外,最简单的修复方法是什么?
4

2 回答 2

1

it takes 3-4 repaints due to any reason (easiest to reproduce is repaint on rollover) for the background to become completely opaque.

Check out Backgrounds With Transparency which should give you some insight into the problem.

I've never played with Synth so I don't know if the same solution will work or not.

于 2013-08-29T19:07:25.497 回答
0

为什么顶层窗口不显示重影?

根据 Oracle(Java 教程):

每个顶级容器都有一个内容窗格,一般来说,它包含(直接或间接)该顶级容器的 GUI 中的可见组件。

http://docs.oracle.com/javase/tutorial/uiswing/components/toplevel.html

在此处输入图像描述

玻璃窗格通常用于拦截发生在顶级容器上的输入事件,也可用于绘制多个组件。它不允许透明度。

因此,您如何使用

final Graphics g2 = g.create();

如果您在与自己创建图形对象相反的方法中覆盖了javax.swing.JComponent.paintComponent,它应该通过 super.g(); 减轻透明度。

通过为图形创建上面列出的单独方法来解决此问题

于 2013-09-07T14:41:30.487 回答