在Java2D中,当你使用setOpaque时,我对true和false的含义感到困惑。
例如我知道在Swing Opaque中意味着在绘制Swing时不会绘制组件后面的内容。或者这是倒退?它是哪一个?
由于
答案 0 :(得分:46)
您问题的简短回答是“不透明”在英语中定义为完全不透明。因此,不透明的组件是绘制整个矩形的组件,并且每个像素都不是半透明到任何程度。
但是,Swing组件opacity API是那些设计错误的API之一,因此经常使用不当的API。
重要的是要理解,isOpaque
是Swing系统和特定组件之间的契约。如果它返回true,则组件保证非半透明地绘制其矩形区域的每个像素。此API 应该是抽象的,以强制所有组件编写者考虑它。 Swing绘画系统使用isOpaque
API来确定给定组件所覆盖的区域是否必须为 绘制与其重叠且位于其后面的组件 ,包括组件的容器和祖先。如果组件对此API返回true,则Swing系统可以优化绘制,以便在调用特定组件的绘制方法之前不在该区域中绘制任何内容。
由于isOpaque
的合同含义,API setOpaque
不应该存在,因为对于调用setOpaque
外部的任何内容实际上都是错误的,因为转而,外部的东西无法知道有问题的组件是否会(甚至可以)尊重它。相反,isOpaque应该被每个具体组件覆盖,以返回它实际上是否实际上是不透明的,因为它的当前属性。
由于setOpaque
API 确实存在,许多组件都错误地实现了它(完全可以理解)来驱动它们是否会绘制它们的“背景”(例如JLabel和JPanel)填充背景颜色)。这样做的结果是使用API的用户创建一个展示,以认为setOpaque
驱动该背景是否应该绘制,但事实并非如此。
此外,如果您想要绘制具有半透明背景的JLabel,您需要设置具有alpha值的背景颜色,并执行setOpaque(true),但它实际上不是不透明的 - 它是半透明的< / em>的;它背后的组件仍然需要绘制,以便组件正确呈现。
这个问题在Java 6的新Nimbus Look&amp; amp;感觉。关于针对Nimbus提交的透明组件有很多错误报告(请参阅堆栈溢出问题Java Nimbus LAF with transparent text fields)。 Nimbus开发团队的反应如下:
这是Swing的原始设计中的一个问题,以及它多年来一直令人困惑的问题。问题是setOpaque(false)在[现有] LAF中产生了一个副作用,即隐藏背景并不是它的意思。这意味着组件可能具有透明部分,[Swing]应该在其后面绘制父组件。
因此,总而言之,您不应该使用setOpaque
。如果您确实使用它,请记住一些Look&amp; amp;感觉和一些组件可能会做“令人惊讶”的事情。最后,实际上没有正确答案。
答案 1 :(得分:1)
javadoc说:如果为true,则组件会绘制其边界内的每个像素。否则,组件可能无法绘制部分或全部像素,允许底层像素显示。
尝试这个示例程序...... http://www.java2s.com/Code/JavaAPI/javax.swing/JPanelsetOpaquebooleanisOpaque.htm
答案 2 :(得分:0)
我认为还需要添加以下内容:
术语 opaque 在Java 2D和Swing中有不同的含义。
在Java 2D中,不透明度是一种渲染概念。这是一个组合
alpha值和Composite
模式。这是一个学位
要绘制的像素颜色应与像素混合
价值已经存在。例如,我们绘制一个半透明的
现有椭圆形的矩形。因此椭圆形
部分可见。这个概念经常被比作光
通过玻璃或水。
在Swing中,不透明组件会绘制其中的每个像素 矩形边界。非不透明组件仅绘制一部分 它的像素或根本没有,允许它下面的像素 透过。不透明的属性是出于效率原因而设定的;摇摆 不必在不透明组件后面绘制区域。
来源:Java docs和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);
}
});
}
}
在代码示例中,我们有两个组件。左侧的组件是一个面板,它使用AlphaComposite
在椭圆上绘制一个高度半透明的矩形。右侧的组件是标签。标签在大多数外观和感觉上都是不透明的。我们覆盖标签的isOpaque()
方法以设置灰色背景。