setOpaque(真/假); Java的

时间:2010-03-16 03:42:26

标签: java swing graphics java-2d

在Java2D中,当你使用setOpaque时,我对true和false的含义感到困惑。

例如我知道在Swing Opaque中意味着在绘制Swing时不会绘制组件后面的内容。或者这是倒退?它是哪一个?

由于

3 个答案:

答案 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()方法以设置灰色背景。

Opaque explained