有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

带有透明文本字段的swing Java Nimbus LAF

我有一个应用程序,它在几个地方使用禁用的JTextFields,这些地方都是透明的——允许背景显示,而不是文本字段的正常背景

运行新的Nimbus LAF时,这些字段是不透明的(尽管设置了setOpaque(false)),并且我的UI被破坏。这就好像LAF忽略了不透明属性。显式设置背景色在一些地方都很困难,而且由于背景图像实际上不起作用而不是最佳的,它仍然在顶部绘制LAF默认背景,留下类似边框的外观(下面的启动屏幕将背景显式设置为与图像匹配)

关于如何让Nimbus不为JTextField绘制背景,有什么想法吗

注意:我需要一个JTextField,而不是JLabel,因为我需要线程安全的setText()和包装功能

注意:我的退路是继续使用系统LAF,但Nimbus看起来确实更好

请参见下面的示例图像


结论

对这种行为的惊讶是由于对setOpaque()的意图的误解——来自Nimbus bug报告:

This is a problem the the orginal design of Swing and how it has been confusing for years. The issue is setOpaque(false) has had a side effect in exiting LAFs which is that of hiding the background which is not really what it is ment for. It is ment to say that the component my have transparent parts and swing should paint the parent component behind it.

不幸的是,Nimbus组件似乎也不支持setBackground(null),否则这将是停止背景绘制的推荐方法。设置一个完全透明的背景对我来说似乎不太直观

在我看来,setOpaque()/isOpaque()是一个错误的公共API选择,它应该是:

public boolean isFullyOpaque();

我这样说是因为isOpaque()==true是与Swing的约定,组件子类将负责绘制整个背景-这意味着父类可以根据需要跳过绘制该区域(这是一个重要的性能增强)。外部事物不能直接(合法地)更改此合同,其履行可能被编码到组件中

因此,不应使用setOpaque()设置组件的不透明度。相反,像setBackground(null)这样的东西应该会导致许多组件“没有背景”,因此变得不完全不透明。例如,在理想情况下,大多数组件都应该有一个如下所示的isOpaque():

public boolean isOpaque() { return (background!=null); }

Example

alt text


共 (4) 个答案

  1. # 1 楼答案

    嘿,这是软件猴子

    安装UI的子类替换,实际上尊重set不透明行为,怎么样

    我认为它是像setUI之类的东西

    你可以抓取nimbus的源代码,看看有什么坏掉了(如果有的话),对它进行子类化,然后安装“修复的”一个

    你的声音很有趣,你有我们能看到的截图吗

  2. # 2 楼答案

    上周我使用JTextPane遇到了同样的问题。当使用除nimbus之外的任何外观时,set不透明()方法都能正常工作。显然,nimbus的外观改变了我们对许多组件使用set不透明()所期望的行为。根据您对它的看法,它可以被视为一个bug。检查此sun bugid上的注释:

    nimbus opaque bug

    对我有效的解决办法是:

    myPane.setOpaque(false); // added by OP
    myPane.setBorder(BorderFactory.createEmptyBorder());
    myPane.setBackground(new Color(0,0,0,0));
    

    OP中的注释:我还必须确保JTextField的setOpaque(false),以便绘制父背景-只是想向其他跟随者提及这一点,以防他们像我一样尝试过setOpaque(true)

  3. # 3 楼答案

    我认为问题在于如何解释“不透明”和“背景”。 对于JTextfield,有一个问题:“背景是什么可见部分?”。我将“背景”定义为边界矩形中未由组件绘制的部分。 例如,对于“圆形”按钮,这将是圆外的角。 因此,我认为JTextfield没有可见的背景!它有一个矩形的形状,你所选择的背景不是场的背景,而是场的画布


    OP的反驳

    这是一个非常有趣的想法,值得在未来观众的回答中回应(而不是在评论中)

    我不同意。我认为边界之外的组件部分不是组件的一部分-它是组件之外的组件。具有圆角的字段必然是非不透明的,因为它不能负责绘制整个矩形区域-这是所有组件在尺寸上都是矩形的副作用

    我认为这种考虑为isOpaque()的现有(和被误解)含义提供了理由。它还提出我的论点,setOpaque()不应该存在,setBackground(null)应该导致组件不绘制背景

    我想指出的是,文本字段的背景确实是其边界内区域的颜色,我认为你不会发现有太多人质疑这一直观结论——因此,将背景应用于该区域符合API用户最不惊讶的规则

  4. # 4 楼答案

    来自javadoc

    public void setBackground(Color bg)

    Sets the background color of this component. The background color is used only if the component is opaque, and only by subclasses of JComponent or ComponentUI implementations. Direct subclasses of JComponent must override paintComponent to honor this property.

    It is up to the look and feel to honor this property, some may choose to ignore it.