Java 如何覆盖单个按钮的Nimbus按钮边距

Java 如何覆盖单个按钮的Nimbus按钮边距,java,swing,jbutton,nimbus,Java,Swing,Jbutton,Nimbus,我创建了一个文本字段组件,里面有一个“x”按钮,可以清除字段的文本。它在使用Windows的系统外观时效果非常好(适用于Windows),但是在使用Nimbus时,我在尝试获得正确的外观时遇到了问题-即,我无法使用button.setMargin(新插图(0,0,0,0)更改按钮上的边距,因为我可以使用系统外观 在使用Nimbus时,我确实在寻找设置边距的帮助,这似乎是一个常见问题。我找到了一个部分解决方案,允许我更改边距,但它会更改所有按钮的边距,我只希望单个按钮与默认按钮不同 我显式地设置了

我创建了一个文本字段组件,里面有一个“x”按钮,可以清除字段的文本。它在使用Windows的系统外观时效果非常好(适用于Windows),但是在使用Nimbus时,我在尝试获得正确的外观时遇到了问题-即,我无法使用
button.setMargin(新插图(0,0,0,0)
更改按钮上的边距,因为我可以使用系统外观

在使用Nimbus时,我确实在寻找设置边距的帮助,这似乎是一个常见问题。我找到了一个部分解决方案,允许我更改边距,但它会更改所有按钮的边距,我只希望单个按钮与默认按钮不同

我显式地设置了“x”按钮的大小,它是根据“x”字符串的边界计算出来的,因此它刚好足够大,可以显示“x”

使用Window的系统外观时的结果,这是我想要的总体外观:

使用默认Nimbus外观时的结果;'x'溢出Nimbus允许的空间,导致省略号

使用Nimbus并覆盖按钮时的结果。contentMargins:现在“x”按钮看起来正确,但“测试”按钮看起来很糟糕

源代码:

import java.awt.Graphics;
import java.awt.Insets;
import java.awt.geom.Rectangle2D;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.LookAndFeel;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.UnsupportedLookAndFeelException;

public class TextFieldTest {        
    public static void main(String[] args) {
        boolean useNimbusLookAndFeel    = false;
        boolean overrideNimbusDefaults  = false;
        String lafName = UIManager.getSystemLookAndFeelClassName();

        if ( useNimbusLookAndFeel ) {
            for ( LookAndFeelInfo info : UIManager.getInstalledLookAndFeels() ) {
                if ( "Nimbus".equals(info.getName()) ) {
                    lafName = info.getClassName();      
                    break;
                }
            }
        }

        try {
            UIManager.setLookAndFeel(lafName);              
        }
        catch (ClassNotFoundException e) {}
        catch (InstantiationException e) {}
        catch (IllegalAccessException e) {}
        catch (UnsupportedLookAndFeelException e) {}

        //Code to set override default button insets for Nimbus:
        if ( useNimbusLookAndFeel && overrideNimbusDefaults ) {
            LookAndFeel laf = UIManager.getLookAndFeel();               
            if ( laf != null ) {
                UIDefaults def = laf.getDefaults();
                def.put("Button.contentMargins", new Insets(0,0,0,0));
            }
        }       

        //Create frame:
        JPanel panel = new JPanel();        
        panel.add(new JButton("test"));
        panel.add(new DeletableTextField());

        JFrame frame = new JFrame();
        frame.getContentPane().add(panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }   

    static class DeletableTextField extends JTextField {
        JButton         mButton     = null;

        public DeletableTextField() {
            super(30);
            setup();
        }

        private void setup() {
            mButton = new JButton("x");
            mButton.setMargin(new Insets(0, 0, 0, 0));
            add(mButton);
        }

        @Override
        public void paint(Graphics g) {
            g.setFont(mButton.getFont());
            Rectangle2D rect    = g.getFontMetrics().getStringBounds(mButton.getText(), g);
            int stringWidth     = (int)rect.getWidth();

            int topOffset       = 3;
            int rightOffset     = 3;
            int bottomOffset    = 3;
            int width           = (int)Math.ceil(stringWidth * 2.5);
            int height          = getHeight() - (bottomOffset + topOffset);         
            int x_coord         = getWidth() - (rightOffset + width);

            mButton.setMargin(new Insets(0, 0, 0, 0));
            mButton.setBounds(x_coord, topOffset, width, height);

            super.paint(g);
        }
    }
}
我知道我可以通过其他方式完成这一点,比如在顶部绘制我自己的“x”,但我认为最好利用当前look and feel的按钮绘制功能来实现统一的外观


因此,我想问一下,在使用Nimbus look and feel时,是否有任何方法可以在不更改所有按钮的边距的情况下更改单个JButton的边距。或者,如果已经有一个看起来类似的swing组件(带有“x”按钮的文本字段),我可以用它来代替。

你能用一种较小的尺寸变体,然后让按钮以其首选尺寸显示,这样就保证有足够的空间来显示文本吗


也许,作为一种黑客,您可以尝试使用左/右插入值并使其非零,以便文本在两个LAF中显示

我知道我可以通过其他方式来完成这一点,比如在上面画我自己的“x”

如果涉及到这一点,那么您可能可以使用该类为您进行自定义绘制。

Nimbus支持,在您的上下文中类似于:

  mButton = new JButton("x");
  UIDefaults def = new UIDefaults();
  def.put("Button.contentMargins", new Insets(0,0,0,0));
  mButton.putClientProperty("Nimbus.Overrides", def);

虽然我无法帮助解决您的问题,但该功能非常酷:D gl和修复程序!我尝试了最小尺寸,但按钮在文本周围的空间仍然比我想要的大,而且“x”太小。但是知道我可以像这样调整组件大小以供将来参考是很有帮助的。谢谢您的回答;这就是我得到的结果查找.My“x”按钮现在至少以三种外观(Mac、Windows和Nimbus)很好地显示。如果您建议这样更改插图:“mButton.setMargin(新插图(0、10、0、10));”,它不适用于Nimbus,因为它会用自己的默认值覆盖任何设置的边距。