Java 中的梯度问题

2022-09-04 07:24:57

在我的程序中,我想在我的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之间的一些区别吗?我应该把底部的颜色变成白色吗?(是黑色的,以防人们想要使底部的颜色变暗。

如果有人需要,我可以发布一些截图tommorrow....

What the gradient should look like

What the gradient actually looks like for some

谢谢杰米

编辑:我将渐变中的第二种(透明)颜色更改为白色,它解决了问题。但是,我仍然很困扰为什么透明的黑色显示在中间?它必须与JRE7有关,因为那是它发生的地方......也许他们改变了渐变透明度的工作方式。有没有人知道如何在保持黑色的同时消除这个问题?


答案 1

这是我的代码版本:

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在他的博客上对此的看法:透明度的背景


答案 2

代码的问题是这行:

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上表现得不同,我猜甲骨文可能已经改变了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);
    }
}

推荐