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

Posted

技术标签:

【中文标题】设置不透明(真/假);爪哇【英文标题】:setOpaque(true/false); Java 【发布时间】:2011-01-27 23:05:57 【问题描述】:

在 Java2D 中,当您使用 setOpaque 时,我对 true 和 false 的作用有点困惑。

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

谢谢

【问题讨论】:

【参考方案1】:

对您的问题的简短回答是,“不透明”在英语中被定义为完全不透明。因此,不透明组件是绘制整个矩形的组件,并且每个像素都不是半透明的。

然而,Swing 组件 opacity 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),但它实际上并不是不透明的 - 它是半透明时间>;它后面的组件仍然需要绘制才能使组件正确呈现。

Java 6 的新 Nimbus Look & Feel 显着暴露了这个问题。有许多关于针对 Nimbus 提交的透明组件的错误报告(请参阅堆栈溢出问题 Java Nimbus LAF with transparent text fields)。 Nimbus 开发团队的回应是这样的:

这是 Swing 原始设计中的一个问题,并且多年来一直令人困惑。问题是 setOpaque(false) 在 [existing] LAF 中产生了副作用,即隐藏背景,而这并不是它 [意味着] 的真正用途。 [意思是]说组件可能有透明部分,[Swing]应该在它后面绘制父组件。

因此,总而言之,您不应该使用setOpaque。如果您确实使用它,请记住某些外观和某些组件的组合可能会做“令人惊讶”的事情。而且,到最后,其实并没有正确的答案。

【讨论】:

迟到了,但感谢您解释 isOpaque 和 alpha 通道之间的关系。我被难住了,因为它们似乎覆盖了同一个区域——知道那是有帮助的,因为 isOpaque 是愚蠢的。 :) 应该将其更改为setPaintBackground(boolean)....或将参数更改为从0到1的浮点因子,以设置不透明度......0是透明的,1 完全不是。 @FaithReaper:该 API 必须被弃用,并用正确规范的东西和 protected 替换。【参考方案2】:

我觉得还需要补充以下几点:

不透明这个词在 Java 2D 和 Swing 中有不同的含义。

在 Java 2D 中,不透明度是一个渲染概念。这是一个组合 alpha 值和Composite 模式。这是一个学位 正在绘制的像素颜色应与像素混合 已经存在的值。例如,我们画一个半透明的 现有椭圆形上的矩形。因此椭圆形是 部分可见。这个概念经常被比作光 穿过玻璃或水。

在 Swing 中,一个不透明的组件绘制其内部的每个像素 矩形边界。一个不透明的组件只绘制一个子集 它的像素或根本没有,允许它下面的像素 通过展示。 opaque 属性是出于效率原因而设置的;摇摆 不必在不透明组件后面绘制区域。

来源: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); );

在代码示例中,我们有两个组件。左边的组件是一个面板,它使用AlphaComposite 在椭圆上绘制一个高度半透明的矩形。右边的组件是一个标签。标签在大多数外观和感觉中都是不透明的。我们覆盖标签的isOpaque() 方法来设置灰色背景。

【讨论】:

【参考方案3】:

javadoc 说:如果为 true,则组件绘制其边界内的每个像素。否则,组件可能不会绘制其部分或全部像素,允许底层像素显示出来。

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

【讨论】:

如果为true,则不显示后面的组件.. 如果为false,则显示.. 我们不需要看javadoc,一本英文字典就足够了 :) :) : ) 是的,我就是这么想的,但是在阅读了很多东西之后,我感到很困惑。谢谢:)

以上是关于设置不透明(真/假);爪哇的主要内容,如果未能解决你的问题,请参考以下文章

EXCEL函数。 如果A1等于1-50数据中的任何一个, 则A2返回“真”, 否则返回“假”, 如何设置函数。

为啥在 undertow 服务器中将端口设置为 80 失败? (爪哇)

节点、Sequelize、同步模型、混合力:真/假

Adaboost weka 真阳性与假阳性识别问题

如何在 android 日期选择器中将特定选定日期设置为最小日期? (爪哇)

CSS3教程:真·任意角度扇形画法