13

在我的程序中,我想在我的 JFrame 上使用半透明的白色到透明的渐变来覆盖黄色背景。这工作正常,它需要是白色到透明的,因为我的程序设置如何为用户工作。但是,当我将程序带入大学时(JRE7 到我的 JRE6),渐变从白色变为黑色然后透明......在你开始增加白色的不透明度之前,这还不错......无论如何我可以解决这个问题吗?

这是我的 JFrame 代码顶部的相关代码。

public class DictionaryGUI extends JFrame
{   
    protected JPanel pGradientPane;

    //Interface gradient specification
    private Color pInterfaceColour = new Color(255, 245, 62);
    protected int iDegreeWhite = 180
    protected int iDegreeBlack = 0

    DictionaryGUI(int iWidth, int iHeight)
    {
        /*General definitions*/
        super(String.format("French Verb Conjugator - Version %s", MainLauncher.version));
        setSize(iWidth, iHeight);
        new Menu(this);

        this.iWidth = iWidth;    
        this.iHeight = iHeight;

        getContentPane().setBackground(pInterfaceColour);
        pGradientPane = new JPanel(new GridBagLayout())
        {
            private static final long serialVersionUID = 1L;

            protected void paintComponent(Graphics pGraphics) 
            {
                Graphics2D pGraphicsGradientRender = (Graphics2D) pGraphics;
                pGraphicsGradientRender.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                GradientPaint pGradient = new GradientPaint(0, 0, new Color(255, 255, 255, iDegreeWhite), 0, getHeight(), new Color(0, 0, 0, iDegreeBlack));
                pGraphicsGradientRender.setPaint(pGradient);
                pGraphicsGradientRender.fillRect(0, 0, getWidth(), getHeight());
                super.paintComponent(pGraphics);
            }
        };
        pGradientPane.setOpaque(false);
        pGradientPane.setPreferredSize(new Dimension(iWidth - 16, iHeight - 62));
        /*components added to pGradientPane here!*/
        add(pGradientPane);
    }

还有主类:

public class MainLauncher
{
    static int iHeight = 400;
    static int iWidth = 730;
    static String version = "0A3B6";

    public static void main(String[] args)
    {
    try 
    {
        for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
        {
            if ("Nimbus".equals(info.getName()))
            {
                UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    } catch (Exception e) {e.printStackTrace();}
    DictionaryGUI window = new DictionaryGUI(iWidth, iHeight);
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.setLocationByPlatform(true);
    window.setVisible(true);
}

JRE6和JRE7之间只是有些区别吗?我也应该将底部颜色设为白色吗?(如果人们想使底部的颜色变暗,是黑色的。)

如果有人需要,我明天可以发布一些屏幕截图......

渐变应该是什么样子

对于某些人来说,渐变实际上是什么样的

谢谢杰米

编辑: 我将渐变中的第二种(透明)颜色更改为白色,它解决了问题。但是,我仍然很困惑为什么透明的黑色会在中间透出来?它一定与 JRE7 有关,因为这就是它发生的地方……也许他们改变了渐变透明度的工作方式。有谁知道如何在保持黑色的同时消除这个问题?

4

5 回答 5

10

这是我作为sscce的代码版本:

import java.awt.*;
import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;

public class MainLauncher {
   static int iHeight = 400;
   static int iWidth = 730;
   static String version = "0A3B6";

   public static void main(String[] args) {
      try {
         for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
               UIManager.setLookAndFeel(info.getClassName());
               break;
            }
         }
      } catch (Exception e) {
         e.printStackTrace();
      }
      DictionaryGUI window = new DictionaryGUI(iWidth, iHeight);
      window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      window.setLocationByPlatform(true);
      window.setVisible(true);
   }

}

class DictionaryGUI extends JFrame {
   protected JPanel pGradientPane;

   // Interface gradient specification
   private Color pInterfaceColour = new Color(255, 245, 62);
   protected int iDegreeWhite = 180;
   protected int iDegreeBlack = 0;

   DictionaryGUI(int iWidth, int iHeight) {
      /* General definitions */
      super(String.format("French Verb Conjugator - Version %s",
            MainLauncher.version));
      setSize(iWidth, iHeight);

      getContentPane().setBackground(pInterfaceColour);
      pGradientPane = new JPanel() {
         private static final long serialVersionUID = 1L;

         protected void paintComponent(Graphics pGraphics) {
            Graphics2D pGraphicsGradientRender = (Graphics2D) pGraphics;
            pGraphicsGradientRender.setRenderingHint(
                  RenderingHints.KEY_ANTIALIASING,
                  RenderingHints.VALUE_ANTIALIAS_ON);
            GradientPaint pGradient = new GradientPaint(0, 0, new Color(255,
                  255, 255, iDegreeWhite), 0, getHeight(), new Color(0, 0, 0,
                  iDegreeBlack));
            pGraphicsGradientRender.setPaint(pGradient);
            pGraphicsGradientRender.fillRect(0, 0, getWidth(), getHeight());
            super.paintComponent(pGraphics);
         }
      };
      pGradientPane.setOpaque(false);
      pGradientPane.setPreferredSize(new Dimension(iWidth - 16, iHeight - 62));
      /* components added to pGradientPane here! */
      add(pGradientPane);
   }
}

但这又不能证明你的问题。我猜你的问题是在 Swing GUI 中使用透明背景,其中绘画伪影没有完全纠正。如果是这样,请阅读 Rob Camick 在他的博客上对此的评论:背景与透明度

于 2012-12-06T17:44:37.763 回答
7

代码的问题是这一行:

GradientPaint pGradient = new GradientPaint(0, 0, new Color(255, 255, 255, iDegreeWhite), 0, getHeight(), new Color(0, 0, 0, iDegreeBlack));

应该是这样的:

GradientPaint pGradient = new GradientPaint(0, 0, new Color(255, 255, 255, iDegreeWhite), 0, getHeight(), new Color(255, 245, 62, iDegreeWhite));

回顾您的问题,我发现您基本上找到了解决方案 - 但它有点不同。原因如下:

在渐变中混合颜色时,您混合颜色的所有方面:RBGA

你看,直到你达到完整的第二种颜色,你将黑色混合到颜色渐变中,并且混合不会完全透明。所以在页面向下的 20% 处,您将拥有以下颜色:204,204,204,144(即 80% 白色、20% 黑色和 56% 不透明)。

最简单的解决方案是在不使用时完全避免半透明——只需从顶部的浅黄色混合到底部的深黄色即可。这种方式也占用更少的资源。

但是由于您使用的是透明度,所以我提供的解决方案也使用了透明度。您将使用一致的透明度从白色混合到黄色。

如果你从白色混合到白色(透明),你会遇到和以前一样的问题,只有白色(因为它是你正在使用的颜色之一,所以不太明显):渐变会有白色“条纹”直到第二种颜色达到完全透明。

至于为什么它在不同的 JVM 上表现不同,我猜 Oracle 可能已经改变了混合 alpha 的方式。更好的 alpha 支持似乎是他们一段时间以来一直在努力的事情,这是朝着这个方向迈出的合乎逻辑的一步。不过,我对此声明没有任何证据——它只是基于我在 alpha 中看到的其他变化(如透明窗口)。

编辑 这个 SSCCE 演示了问题和解决方案:

import java.awt.*;
import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;


public class TransparencyDemo extends Box{

    protected JPanel pGradientPane;

    //Interface gradient specification
    private Color pInterfaceColour = new Color(255, 245, 62);
    protected int iDegreeWhite = 180;
    protected int iDegreeBlack = 0;

    public TransparencyDemo() {
        super(BoxLayout.X_AXIS);
        setOpaque(true);

        //Incorrect Solution
        pGradientPane = new JPanel(new GridBagLayout())
        {
            private static final long serialVersionUID = 1L;

            protected void paintComponent(Graphics pGraphics) 
            {
                Graphics2D pGraphicsGradientRender = (Graphics2D) pGraphics;
                pGraphicsGradientRender.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                GradientPaint pGradient = new GradientPaint(0, 0, new Color(255, 255, 255, iDegreeWhite), 0, getHeight(), new Color(0, 0, 0, iDegreeBlack));
                pGraphicsGradientRender.setPaint(pGradient);
                pGraphicsGradientRender.fillRect(0, 0, getWidth(), getHeight());
                super.paintComponent(pGraphics);
            }
        };
        pGradientPane.setOpaque(false);
        add(pGradientPane);

        //Correct Solution
        JPanel pGradientPane2 = new JPanel(new GridBagLayout())
        {
            private static final long serialVersionUID = 1L;

            protected void paintComponent(Graphics pGraphics) 
            {
                Graphics2D pGraphicsGradientRender = (Graphics2D) pGraphics;
                pGraphicsGradientRender.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                GradientPaint pGradient = new GradientPaint(0, 0, new Color(255, 255, 255, iDegreeWhite), 0, getHeight(),  new Color(255, 245, 62, iDegreeWhite));
                pGraphicsGradientRender.setPaint(pGradient);
                pGraphicsGradientRender.fillRect(0, 0, getWidth(), getHeight());
                super.paintComponent(pGraphics);
            }
        };
        pGradientPane2.setOpaque(false);
        add(pGradientPane2);


        setBackground(pInterfaceColour);

    }

    public static void main(String[] args){
        try {
             for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                   UIManager.setLookAndFeel(info.getClassName());
                   break;
                }
             }
          } catch (Exception e) {
             e.printStackTrace();
          }

        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new TransparencyDemo());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
于 2012-12-10T17:41:15.670 回答
6

我的猜测是,它与不同计算机上使用的“图形管道”有关。

Java 有几个不同的管道,这里有一些关于它们的信息。

在我的计算机上,我可以使用 X11 管道或 OpenGL 管道。使用 X11 管道时会出现黑暗;在 OpenGL 上,它没有。

在 Windows 上,您可以从 3 种不同的管道中进行选择,即使这样(查看上面的链接),也可能存在差异。

我无法立即想象您学校的配置是什么,以及为什么会有所不同,但是您可以尝试调查一下。

您可能希望将此差异归档为错误。

于 2012-12-09T19:14:17.273 回答
2

正如尼克指出的那样,问题在于您使用的是透明黑色而不是透明白色。所以半透明的颜色是介于白色和黑色之间的阴影。

尝试用代码中的这一行替换:

GradientPaint pGradient = new GradientPaint(0, 0, new Color(255, 255, 255, iDegreeWhite), 0, getHeight(), new Color(255, 255, 255, iDegreeBlack));
于 2012-12-11T15:09:59.503 回答
2

我有fatamorgana,我确定GradientPaint越来越黑越来越黑,phaaa疯狂的眼睛错觉,brrrr

//http://stackoverflow.com/questions/13748810/gradient-problems-in-java/13806210#comment18995490_13806210

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.RepaintManager;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;

public class MainLauncher {

    private JFrame window = new JFrame();

    public MainLauncher() {
        GradientPane pane = new GradientPane();
        pane.setLayout(new GridLayout(6, 4, 15, 15));
        for (int i = 1; i <= 24; i++) {
            pane.add(createButton(i));
        }
        pane.setOpaque(false);
        window.add(pane);
        RepaintManager.setCurrentManager(new RepaintManager() {

            @Override
            public void addDirtyRegion(JComponent c, int x, int y, int w, int h) {
                Container con = c.getParent();
                while (con instanceof JComponent) {
                    if (!con.isVisible()) {
                        return;
                    }
                    if (con instanceof GradientPane) {
                        c = (JComponent) con;
                        x = 0;
                        y = 0;
                        w = con.getWidth();
                        h = con.getHeight();
                    }
                    con = con.getParent();
                }
                super.addDirtyRegion(c, x, y, w, h);
            }
        });
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setLocationByPlatform(true);
        window.setSize(400, 300);
        //window.pack();
        window.setVisible(true);
    }

    private JButton createButton(final int text) {
        JButton button = new JButton(Integer.toString(text));
        return button;
    }

    class GradientPane extends JPanel {

        private static final long serialVersionUID = 1L;
        private final int h = 150;
        private BufferedImage img = null;
        private BufferedImage shadow = new BufferedImage(1, h, BufferedImage.TYPE_INT_ARGB);

        public GradientPane() {
            paintBackGround(new Color(150, 250, 150));
        }

        public void paintBackGround(Color g) {
            Graphics2D g2 = shadow.createGraphics();
            g2.setPaint(g);
            g2.fillRect(0, 0, 1, h);
            g2.setComposite(AlphaComposite.DstIn);
            g2.setPaint(new GradientPaint(0, 0, new Color(0, 0, 0, 0f), 0, h, new Color(0.1f, 0.8f, 0.8f, 0.5f)));
            g2.fillRect(0, 0, 1, h);
            g2.dispose();
        }

        @Override
        public void paintComponent(Graphics g) {
            if (img == null || img.getWidth() != getWidth() || img.getHeight() != getHeight()) {
                img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
            }
            Graphics2D g2 = img.createGraphics();
            super.paintComponent(g2);
            Rectangle bounds = this.getVisibleRect();
            g2.scale(bounds.getWidth(), -1);
            g2.drawImage(shadow, bounds.x, -bounds.y - h, null);
            g2.scale(1, -1);
            g2.drawImage(shadow, bounds.x, bounds.y + bounds.height - h, null);
            g2.dispose();
            g.drawImage(img, 0, 0, null);
        }
    }

    public static void main(String[] args) {
        try {
            for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                MainLauncher ml = new MainLauncher();
            }
        });
    }
}
于 2012-12-10T22:36:56.780 回答