【问题标题】:Non-opaque JButton background in non top level window becomes opaque?非顶级窗口中的非透明 JButton 背景变得不透明?
【发布时间】:2013-09-02 05:51:22
【问题描述】:

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

  1. SSCCE 是为 Java 7 设计的。可以使用 sun.*.AWTUtilities 使其适应 Java 6,但它在 Java 6 上的工作方式对我来说并不重要。
  2. 故障线路是[...]new JDialog(someWindow)可以修复 SSCCE 中的重影问题只需将该行更改为[...]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();
                        }
                }
        }
}

这些是我的问题......

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

【问题讨论】:

  • 请将您的 SSCCE 代码粘贴到此处,而不是链接中。
  • 将链接替换为完整代码。
  • @mKorbel:不幸的是,该问题/答案中显示的代码明显远离任何非 TL 窗口。我不在乎 super("Test translucent window"); 工作正常,因为我需要非 TL 窗口,不幸的是它表现出一些奇怪的行为。
  • huuuh,但在 Java6 中对我有用 ...

标签: java swing user-interface synth jwindow


【解决方案1】:

由于任何原因(最容易重现的是在翻转时重新绘制),背景需要重新绘制 3-4 次才能完全不透明。

查看Backgrounds With Transparency,它应该可以让您对问题有所了解。

我从来没有玩过 Synth,所以我不知道相同的解决方案是否可行。

【讨论】:

  • Synth 不遵循 Nimbus L&F 之前的普遍共识,即不透明组件是绘制其背景的组件,反之亦然。 Synth 允许非透明组件按应有的方式绘制其背景(对于某些组件,UIDefaults 中的 isContentAreaFilled 控制是否绘制背景)。 主要问题是为什么一切都可以在 TL 窗口上运行,但不能在非 TL 窗口上运行?
【解决方案2】:

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

根据 Oracle(Java 教程):

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

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

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

因此你是如何使用的

final Graphics g2 = g.create();

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

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

【讨论】:

  • 严重怀疑玻璃板是否与问题有关:f.i.这将如何解释 new JDialog() 与 new JDialog(frame) 的不同行为?
  • 所有组件都添加到内容窗格中。玻璃板完全未使用(可以在 SSCCE 中看到)。
猜你喜欢
  • 2018-07-06
  • 1970-01-01
  • 1970-01-01
  • 2022-01-24
  • 1970-01-01
  • 2011-10-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多