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

标签 java swing jbutton nimbus

我已经创建了一个文本字段组件,里面有一个“x”按钮,可以清除该字段的文本。它在使用 Window 的系统外观和感觉(对于 Windows)时效果很好,但是我在使用 Nimbus 时尝试获得正确的外观时遇到了问题 - 也就是说,我无法使用 button.setMargin( new Inset(0, 0, 0, 0) 尽我所能使用系统外观。

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

我明确设置了“x”按钮的大小,根据“x”字符串的边界计算,使其刚好足以显示“x”。

使用Window的系统外观时的结果,也就是我要找的一般外观:

System look and feel

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

Nimbus look and feel

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

Nimbus look and feel, plus margin overrides

源代码:

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”,但我认为最好利用当前外观的按钮绘制功能来获得统一的外观.

所以我想问一下,在使用 Nimbus 外观和感觉时,是否有任何方法可以更改单个 JButton 的边距,而 不会更改所有按钮的边距。或者,如果已经有一个看起来相似的 swing 组件(带有“x”按钮的文本字段),我可以改用它。

最佳答案

Nimbus 支持 per-instance overrides of LAF properties ,在你的上下文中是这样的:

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

关于java - 如何覆盖单个按钮的 Nimbus 按钮边距,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8764602/

相关文章:

java - BorderLayout.CENTER 没有居中我的 JPanel

java - 如何修复 jframe 上的空白屏幕并从文本字段设置 vgap 和 hgap 的值

java - 创建 .ser 文件后可以编辑 .ser java 文件中使用的类吗?

java - 如何替换未附加到字符串的文本中的数字

java - 带有自定义适配器的抽屉导航 react 不正确

java - "AWT-EventQueue-0"java.lang.InternalError : fillbuf

java - 如何在按下按钮时继续执行工作?

java - JButton 的 2D 数组未出现

java - 如何一次创建 100 个 JButton

java - Selenium 网络驱动程序 : How to execute complete Test in testNG for a failed test case