Java2DでsetOpaqueを使用すると、trueとfalseが何をするのか少し混乱します。
たとえば、Swing Opaqueでは、Swingをペイントするときに、コンポーネントの背後にあるものをペイントしないことを意味します。それともこれは逆ですか?どちらですか?
ありがとう
あなたの質問に対する簡単な答えは、「不透明」は英語では完全に不透明であると定義されているということです。したがって、不透明なコンポーネントとは、長方形全体をペイントするコンポーネントであり、すべてのピクセルがまったく半透明ではありません。
ただし、Swingコンポーネントの不透明度APIは、設計が誤っているため、APIの誤用が多いものの1つです。
理解しておくべき重要なことisOpaque
は、Swingシステムと特定のコンポーネントとの間の契約であるということです。trueが返された場合、コンポーネントは、長方形の領域のすべてのピクセルを非半透明にペイントすることを保証します。このAPIは、すべてのコンポーネント作成者にそれを考慮させるために抽象的である必要があります。APIは、 Swingのペイントシステムによって使用され、コンポーネントのコンテナや祖先など、特定のコンポーネントがカバーする領域を、そのコンポーネントと重なり、その背後にあるコンポーネントに対してisOpaque
ペイントする必要があるかどうかを判断します。コンポーネントがこのAPIにtrueを返す場合、Swingシステムは、特定のコンポーネントのペイントメソッドを呼び出すまで、その領域に何もペイントしないようにペイントを最適化する場合があります。
の契約上の影響によりisOpaque
、APIは存在しsetOpaque
ないはずです。これは、外部が呼び出すことは実際には正しくないためですsetOpaque
。外部のものは、問題のコンポーネントがそれを尊重するかどうかを知ることができないためです。代わりに、isOpaqueは、現在のプロパティを考慮して実際に不透明であるかどうかを返すために、各具象コンポーネントによってオーバーライドされている必要があります。
setOpaque
APIが存在するため、多くのコンポーネントは、「背景」をペイントするかどうかを決定するために(当然のことながら)APIを誤って実装しています(たとえば、JLabelやJPanelが背景色で塗りつぶされています)。これの効果は、APIのユーザーsetOpaque
に、その背景をペイントする必要があるかどうかを左右 するという印象を与えることですが、そうではありません。
さらに、たとえば、半透明の背景でJLabelをペイントする場合は、背景色をアルファ値で設定する必要がありますが、setOpaque(true)
実際には不透明ではありません。半透明です。コンポーネントを適切にレンダリングするには、その背後にあるコンポーネントをペイントする必要があります。
この問題は、Java6の新しいNimbusLook&Feelで重大な形で明らかになりました。Nimbusに対して提出された透過コンポーネントに関する多数のバグレポートがあります(透過テキストフィールドを使用したスタックオーバーフローの質問Java Nimbus LAFを参照してください)。ニンバス開発チームの反応は次のとおりです。
これは、Swingの元の設計と、それが何年にもわたってどのように混乱してきたかという問題です。問題は、setOpaque(false)が[既存の] LAFに副作用をもたらしたことです。これは、実際には[意味]ではない背景を非表示にすることです。コンポーネントには透明なパーツがある可能性があり、[Swing]はその背後にある親コンポーネントをペイントする必要があると言うのが[意味]です。
したがって、要約すると、を使用しないでくださいsetOpaque
。それを使用する場合は、いくつかのルックアンドフィールといくつかのコンポーネントの組み合わせが「驚くべき」ことをする可能性があることに注意してください。そして、結局のところ、正しい答えは実際にはありません。
javadocによると:trueの場合、コンポーネントはその境界内のすべてのピクセルをペイントします。そうしないと、コンポーネントがそのピクセルの一部またはすべてをペイントせず、下にあるピクセルが透けて見える可能性があります。
このサンプルプログラムも試してみてください... http://www.java2s.com/Code/JavaAPI/javax.swing/JPanelsetOpaquebooleanisOpaque.htm
以下も追加する必要があると思います。
不透明という用語は、Java2DとSwingでは異なる意味を持っています。
Java 2Dでは、不透明度はレンダリングの概念です。アルファ値とComposite
モードの組み合わせです。これは、描画されるピクセルの色を、すでに存在するピクセル値とブレンドする必要がある度合いです。たとえば、既存の楕円形の上に半透明の長方形を描画します。したがって、楕円形は部分的に表示されます。この概念は、多くの場合、光を通すトラフガラスまたは水と比較されます。
Swingでは、不透明なコンポーネントが長方形の境界内のすべてのピクセルをペイントします。不透明でないコンポーネントは、そのピクセルのサブセットのみをペイントするか、まったくペイントしないため、その下のピクセルが透けて見えます。不透明なプロパティは、効率上の理由から設定されました。Swingは、不透明なコンポーネントの背後の領域をペイントする必要はありません。
出典:JavaドキュメントとFilthy Rich 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()
メソッドを上書きして、灰色の背景を設定します。