Java中的梯度问题

在我的程序中,我希望在我的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有关,因为它发生的地方……也许它们改变了渐变中透明度的工作方式。 有人知道如何在保持颜色变黑的同时消除这个问题吗?

代码的问题是这一行:

 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); } } 

这是我的代码版本作为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); } } 

但这再次certificate了你的问题。 我猜你的问题是使用Swing GUI的透明背景,其中绘画工件没有完全纠正。 如果是这样,请在他的博客上阅读Rob Camick对此的评论: 透明度背景

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

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

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

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

我不能立刻想象你的学校有什么配置,为什么它有所不同,但你可以尝试调查。

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

我有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(); } }); } } 

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

尝试在代码中替换此行:

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