web-dev-qa-db-ja.com

setOpaque(true / false); Java

Java2DでsetOpaqueを使用すると、真と偽が何をするのか少し混乱します。

たとえば、Swing Opaqueでは、Swingをペイントするときに、コンポーネントの背後にあるものをペイントしないことを意味します。それともこれは逆ですか?どちらですか?

ありがとう

13
anon235370

あなたの質問に対する簡単な答えは、「不透明」は英語では完全に不透明であると定義されているということです。したがって、不透明なコンポーネントとは、長方形全体をペイントするコンポーネントであり、すべてのピクセルがまったく半透明ではありません。

ただし、Swingコンポーネントの不透明度APIは、設計が誤っているため、APIの誤用が多いものの1つです。

理解しておくべき重要なことは、isOpaqueはSwingシステムと特定のコンポーネントの間のcontractであるということです。 trueが返された場合、コンポーネントは、長方形領域のすべてのピクセルを非半透明にペイントすることを保証します。このAPI shouldは抽象的であり、すべてのコンポーネント作成者にそれを考慮させます。 isOpaque AP​​Iは、Swingのペイントシステムによって使用され、特定のコンポーネントでカバーされる領域をペイントする必要があるかどうかを判断します重なり、背後にあるコンポーネントの場合、コンポーネントのコンテナと祖先を含みます。コンポーネントがこのAPIにtrueを返す場合、Swingシステムは、特定のコンポーネントのPaintメソッドを呼び出すまで、その領域に何もペイントしないようにペイントを最適化する場合があります。

isOpaqueの契約上の影響により、API setOpaqueすべきではないが存在します。これは、外部からsetOpaqueを呼び出すことは実際には正しくないためです。次に、外部のものは、問題のコンポーネントがそれを尊重するかどうか(またはそれを尊重することさえできるかどうか)を知ることができません。代わりに、isOpaqueを各具象コンポーネントでオーバーライドして、現在のプロパティを考慮して実際に不透明であるかどうかを返す必要があります。

setOpaque AP​​I doesが存在するため、多くのコンポーネントは、「背景」をペイントするかどうかを決定するために、(非常に理解できるように)誤って実装しています(たとえば、JLabelやJPanelはそれらの背景色)。これの効果は、APIのsersで印象を作成し、setOpaqueがその背景をペイントするかどうかを決定するが、そうではないと考えることです。

さらに、たとえば、半透明の背景でJLabelをペイントする場合は、アルファ値で背景色を設定し、setOpaque(true)を実行する必要がありますが、実際には不透明ではありません-半透明;コンポーネントを正しくレンダリングするには、その背後にあるコンポーネントをペイントする必要があります。

この問題は、Java 6の新しいNimbusルックアンドフィールで重大な方法で明らかになりました。Nimbusに対して提出された透過コンポーネントに関する多数のバグレポートがあります(スタックオーバーフローの質問を参照 Java Nimbus LAF透明なテキストフィールドを使用 )Nimbus開発チームの応答は次のとおりです。

これは、Swingの元の設計と、それが何年もの間どのように混乱してきたかという問題です。問題は、setOpaque(false)が[既存の] LAFに副作用をもたらしたことです。これは、実際には[意味]ではない背景を非表示にすることです。コンポーネントに透明なパーツがある可能性があると言うのは[意味]であり、[Swing]はその背後にある親コンポーネントをペイントする必要があります。

したがって、要約すると、setOpaqueは使用しないでください。使用する場合は、ルックアンドフィールとコンポーネントの組み合わせによって「驚くべき」ことが行われる可能性があることに注意してください。そして、結局のところ、正しい答えは実際にはありません。

49
Lawrence Dol

javadoc 言います:trueの場合、コンポーネントはその境界内のすべてのピクセルをペイントします。そうしないと、コンポーネントがそのピクセルの一部またはすべてをペイントできず、下にあるピクセルが透けて見えるようになります。

このサンプルプログラムも試してみてください... http://www.Java2s.com/Code/JavaAPI/javax.swing/JPanelsetOpaquebooleanisOpaque.htm

1
raj

以下も追加する必要があると思います。

opaqueという用語は、Java 2DとSwingでは異なる意味を持ちます。

Java 2D不透明度はレンダリングの概念です。これは、アルファ値とCompositeモードの組み合わせです。これは、描画されるピクセルの色をブレンドする必要がある度合いです。ピクセル値がすでに存在する場合。たとえば、既存の楕円形の上に半透明の長方形を描画します。したがって、楕円は部分的に表示されます。この概念は、ガラスや水を通過する光とよく比較されます。

Swingでは、不透明なコンポーネントが長方形の境界内のすべてのピクセルをペイントします。不透明でないコンポーネントは、そのピクセルのサブセットのみをペイントするか、まったくペイントしないため、その下のピクセルが透けて見えます。不透明なプロパティは、効率上の理由から設定されました。 Swingは、不透明なコンポーネントの背後の領域をペイントする必要はありません。

出典:Java docsおよびFilthyRich Clients

 _package com.zetcode;

import Java.awt.AlphaComposite;
import Java.awt.Color;
import Java.awt.EventQueue;
import Java.awt.Graphics;
import Java.awt.Graphics2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import static javax.swing.SwingConstants.CENTER;
import net.miginfocom.swing.MigLayout;

class DrawingPanel extends JPanel {

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        doDrawing(g);
    }

    private void doDrawing(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;

        g2d.setColor(Color.green);
        g2d.fillOval(20, 20, 100, 100);
        g2d.setColor(Color.blue);
        g2d.setComposite(AlphaComposite.getInstance(
                AlphaComposite.SRC_OVER, 0.1f));
        g2d.fillRect(0, 0, 150, 150);
    }
}

class MyLabel extends JLabel {

    public MyLabel(String text) {
        super(text, null, CENTER);
    }

    @Override
    public boolean isOpaque() {
        return true;
    }
}

public class OpaqueEx2 extends JFrame {

    public OpaqueEx2() {

        initUI();
    }

    private void initUI() {

        JLabel lbl1 = new JLabel("Java 2D opacity");
        JLabel lbl2 = new JLabel("Swing opaque");

        DrawingPanel dpanel = new DrawingPanel();

        MyLabel mylbl = new MyLabel("isOpaque()");
        mylbl.setBackground(Color.decode("#A9A9A9"));

        createLayout(lbl1, lbl2, dpanel, mylbl);

        setTitle("Opaque");
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private void createLayout(JComponent... arg) {

        JPanel pnl = new JPanel(new MigLayout("ins 10"));

        pnl.add(arg[0], "w 150");
        pnl.add(arg[1], "w 150, wrap");
        pnl.add(arg[2], "w 150, h 150");
        pnl.add(arg[3], "w 150, h 150");

        add(pnl);
        pack();
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                OpaqueEx2 ex = new OpaqueEx2();
                ex.setVisible(true);
            }
        });
    }
}
_ 

コード例では、2つのコンポーネントがあります。左側のコンポーネントは、AlphaCompositeを使用して楕円の上に非常に半透明の長方形をペイントするパネルです。右側のコンポーネントはラベルです。ラベルは、ほとんどのルックアンドフィールで不透明ではありません。ラベルのisOpaque()メソッドを上書きして、灰色の背景を設定します。

Opaque explained

0
Jan Bodnar