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の違いはありますか?下の色も白にする必要がありますか?(人々が下部の色を暗くしたい場合に備えて、黒でした。)

誰かがそれらを必要とするならば、私は明日いくつかのスクリーンショットを投稿することができます....

グラデーションはどのように見えるべきか

一部のグラデーションが実際にどのように見えるか

ありがとうジェイミー

編集: グラデーションの2番目の(透明な)色を白に変更すると、問題が修正されます。しかし、なぜ真ん中に透明な黒い色が透けて見えるのか、まだ悩んでいます。それは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で透明な背景を使用していて、ペイントのアーティファクトが完全に修正されていないことだと思います。もしそうなら、ロブ・カミックが彼のブログでこれについて言っていることを読んでください:透明性のある背景

于 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

ご覧のとおり、完全な2番目の色に到達するまで、カラーグラデーションに黒を混合しており、その混合は完全な透明度にはなりません。つまり、ページの20%下がると、次の色になります:204,204,204,144(つまり、80%が白、20%が黒、56%が不透明)。

最も簡単な解決策は、半透明を使用しない場合は完全に回避することです。上部の明るい黄色から下部の暗い黄色までブレンドするだけです。この方法でも、必要なリソースが少なくて済みます。

ただし、透明性を使用しているため、私が提供したソリューションでは透明性も使用しています。一貫した透明度を使用して、白から黄色にブレンドします。

白から白(透明)にブレンドする場合、白だけで以前と同じ問題が発生します(使用している色の1つであるため、目立たなくなります):グラデーションには白の「ストリーク」があります。 2番目の色が完全な透明度に達するまで。

異なるJVMで動作が異なる理由については、Oracleがアルファのブレンド方法を変更した可能性があると思います。より良いアルファサポートは彼らがしばらく取り組んできたもののようであり、これはその方向への論理的なステップです。ただし、このステートメントについての証拠はありません。これは、アルファで見た他の変更(透明なウィンドウなど)に基づいています。

編集 この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はますます暗くなり、暗くなります、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 に答える
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 に答える