简体   繁体   English

设置不透明(真/假); 爪哇

[英]setOpaque(true/false); Java

In Java2D when you use setOpaque I am a little confused on what the true and false does.在 Java2D 中,当您使用 setOpaque 时,我对 true 和 false 的作用有点困惑。

For example I know that in Swing Opaque means that when painting Swing wont paint what is behind the component.例如,我知道在 Swing 中不透明意味着在绘制 Swing 时不会绘制组件后面的内容。 Or is this backwards?或者这是倒退? Which one is it?哪一个?

Thanks谢谢

The short answer to your question is that "opaque" is defined in English as completely non-transparent.对您的问题的简短回答是“不透明”在英语中被定义为完全不透明。 Therefore an opaque component is one which paints its entire rectangle, and every pixel is not at all translucent to any degree.因此,不透明组件是绘制其整个矩形的组件,并且每个像素在任何程度上都不是半透明的。

However, the Swing component opacity API is one of those mis-designed and therefore often mis-used APIs.然而,Swing 组件不透明度 API 是那些设计错误并因此经常被误用的 API 之一。

What's important to understand is that isOpaque is a contract between the Swing system and a particular component.重要的是要理解isOpaque是 Swing 系统和特定组件之间的契约 If it returns true, the component guarantees to non-translucently paint every pixel of its rectangular area.如果返回 true,则组件保证不透明地绘制其矩形区域的每个像素。 This API should have been abstract to force all component writers to consider it.这个 API应该是抽象的,以强制所有组件编写者考虑它。 The isOpaque API is used by Swing's painting system to determine whether the area covered by a given component must be painted for components which overlap it and which are behind it , including the component's container and ancestors. Swing 的绘制系统使用isOpaque API 来确定是否必须为给​​定组件覆盖的区域绘制与其重叠和后面的组件,包括组件的容器和祖先。 If a component returns true to this API, the Swing system may optimize painting to not paint anything in that area until invoking the specific component's paint method.如果某个组件对此 API 返回 true,则 Swing 系统可能会优化绘制,以便在调用特定组件的绘制方法之前不在该区域绘制任何内容。

Because of contractual implication of isOpaque , the API setOpaque should not exist, since it is actually incorrect for anything external to call setOpaque since, in turn, the external thing can't know whether the component in question will (or even can) honor it.由于isOpaque的合同含义,API setOpaque不应该存在,因为实际上任何外部调用setOpaque都是不正确的,因为反过来,外部事物无法知道有问题的组件是否会(甚至可以)兑现它. Instead, isOpaque should have been overridden by each concrete component to return whether it actually is, in fact, opaque given its current properties.相反, isOpaque 应该被每个具体组件覆盖,以返回它是否实际上是不透明的,事实上,鉴于其当前属性。

Because the setOpaque API does exist, many components have mis-implemented it (quite understandably) to drive whether or not they will paint their "background" (for example JLabel and JPanel filling with their background color).因为setOpaque API确实存在,许多组件错误地实现了它(非常可以理解)来驱动它们是否会绘制它们的“背景”(例如 JLabel 和 JPanel 填充它们的背景颜色)。 The effect of this is to create an impression with users of the API to think that setOpaque drives whether or not that background should paint, but it doesn't.这样做的效果是给 API 的用户留下一种印象,认为setOpaque决定了该背景是否应该绘制,但事实并非如此。

Furthermore, if, say, you wish to paint a JLabel with a translucent background you need to set a background color with an alpha value, and do setOpaque(true) , but it's not actually opaque - it's translucent ;此外,如果你想用半透明背景绘制一个 JLabel,你需要设置一个带有 alpha 值的背景颜色,并执行setOpaque(true) ,但它实际上并不是不透明的 - 它是半透明的 the components behind it still need to paint in order for the component to render properly.它后面的组件仍然需要绘制才能正确渲染组件。

This problem was exposed in a significant way with the Java 6's new Nimbus Look & Feel.这个问题在 Java 6 的新 Nimbus Look & Feel 中显着暴露。 There are numerous bug reports regarding transparent components filed against Nimbus (see stack overflow question Java Nimbus LAF with transparent text fields ).有许多关于针对 Nimbus 提交的透明组件的错误报告(请参阅带有透明文本字段的堆栈溢出问题Java Nimbus LAF )。 The response of the Nimbus development team is this: Nimbus 开发团队的回应是这样的:

This is a problem [in] the orginal design of Swing and how it has been confusing for years.这是 Swing 原始设计中的一个问题,多年来一直令人困惑。 The issue is setOpaque(false) has had a side effect in [existing] LAFs which is that of hiding the background which is not really what it is [meant] for.问题是 setOpaque(false) 对 [现有] LAF 产生了副作用,即隐藏背景,而这并不是真正的 [意义]。 It is [meant] to say that the component may have transparent parts and [Swing] should paint the parent component behind it. [意思]是说组件可能有透明部分,[Swing]应该在其后面绘制父组件。

So, in summary, you should not use setOpaque .因此,总而言之,您不应该使用setOpaque If you do use it, bear in mind that the combination of some Look & Feels and some components may do "surprising" things.如果您确实使用它,请记住,某些外观和感觉和某些组件的组合可能会做“令人惊讶”的事情。 And, in the end, there is actually no right answer.而且,最终,实际上没有正确的答案。

javadoc says : If true the component paints every pixel within its bounds. javadoc说:如果为 true,则组件会绘制其边界内的每个像素。 Otherwise, the component may not paint some or all of its pixels, allowing the underlying pixels to show through.否则,组件可能不会绘制其部分或全部像素,从而允许底层像素显示出来。

try this example program too... http://www.java2s.com/Code/JavaAPI/javax.swing/JPanelsetOpaquebooleanisOpaque.htm也试试这个示例程序... http://www.java2s.com/Code/JavaAPI/javax.swing/JPanelsetOpaquebooleanisOpaque.htm

I think that the following also needs to be added:我认为还需要补充以下几点:

The term opaque has different meanings in Java 2D and in Swing.术语不透明在 Java 2D 和 Swing 中具有不同的含义。

In Java 2D opacity is a rendering concept.在 Java 中,2D 不透明度是一个渲染概念。 It is a combination of an alpha value and the Composite mode.它是 alpha 值和Composite模式的Composite It is a degree to which the pixel colours being drawn should be blended with pixel values already present.它是绘制的像素颜色应与已存在的像素值混合的程度。 For instance, we draw a semi-transparent rectangle over an existing oval shape.例如,我们在现有的椭圆形上绘制一个半透明的矩形。 The oval is therefore partially visible.因此椭圆形部分可见。 This concept is often compared to light going trough glass or water.这个概念通常被比作光通过玻璃或水。

In Swing, an opaque component paints every pixel within its rectangular bounds.在 Swing 中,不透明组件在其矩形边界内绘制每个像素。 A non-opaque component paints only a subset of its pixels or none at all, allowing the pixels underneath it to show through.非不透明组件仅绘制其像素的子集或根本不绘制,从而允许其下方的像素显示出来。 The opaque property was set for efficiency reasons; opaque 属性是出于效率原因设置的; Swing does not have to paint areas behind opaque components. Swing 不必在不透明组件后面绘制区域。

Source: Java docs and Filthy Rich Clients来源:Java 文档和肮脏的富客户端

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);
            }
        });
    }
}

In the code example, we have two components.在代码示例中,我们有两个组件。 The component on the left is a panel which uses AlphaComposite to paint a highly translucent rectangle over an oval.左侧的组件是一个面板,它使用AlphaComposite在椭圆上绘制一个高度半透明的矩形。 The component on the right is a label.右边的组件是一个标签。 Labels are non-opaque in most look and feels.标签在大多数外观和感觉中都是不透明的。 We overwrite the label's isOpaque() method to set a gray background.我们覆盖标签的isOpaque()方法来设置灰色背景。

不透明解释

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM