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

发布于 2024-12-25 11:50:01 字数 4039 浏览 1 评论 0原文

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

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

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

使用 Window 系统外观时的结果,这是我正在寻找的一般外观:

系统外观

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

Nimbus Look and Feel

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

Nimbus 外观和感觉,加上边距覆盖

源代码:

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”按钮的文本字段),我也许可以使用它。

I have created a text field component with an 'x' button inside that will clear the field's text. It works great when using Window's system look and feel (for Windows), however I am having problems trying to get the right look when using Nimbus - namely, I can't change the margins on the button using button.setMargin(new Inset(0, 0, 0, 0) as I can with the system look and feel.

I did look for help setting the margins when using Nimbus and it appears to be a common problem. I was able to find a partial solution that does allow me to change the margins, however it changes the margins for all buttons and I want only the single button to be different than the default.

I set the 'x' button size explicitly, calculated from the bounds of the 'x' string so that it is just big enough to display the 'x'.

The result when using Window's system look and feel, which is the general appearance that I'm looking for:

System look and feel

The result when using the default Nimbus look and feel; 'x' overflows the space Nimbus allows for it, resulting in an ellipsis.

Nimbus look and feel

The result when using Nimbus and overriding the Button.contentMargins: Now the 'x' button looks correct, but the 'test' button looks awful.

Nimbus look and feel, plus margin overrides

Source code:

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

I am aware that I can accomplish this in other ways, like painting my own 'x' on top, but I thought it would be nice to take advantage of the current look-and-feel's button painting abilities for a unified look.

So I would like to ask if there is any way to change a single JButton's margins when using the Nimbus look and feel without changing the margins for all the buttons. Alternatively, if there's already a swing component out there that looks similar (text field with 'x' button), I may be able to use that instead.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

空心空情空意 2025-01-01 11:50:01

Nimbus 支持按实例覆盖 LAF 属性,在您的上下文中类似:

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

Nimbus supports per-instance overrides of LAF properties, in your context something like:

  mButton = new JButton("x");
  UIDefaults def = new UIDefaults();
  def.put("Button.contentMargins", new Insets(0,0,0,0));
  mButton.putClientProperty("Nimbus.Overrides", def);
冰之心 2025-01-01 11:50:01

您能否使用较小尺寸的变体之一,然后让按钮以其首选尺寸显示,以便保证有文本空间?

http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel /尺寸.html

Could you use one of the smaller size variants, and then let the button display at its preferred size so that there is guaranteed to be space for the text?

http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/size.html

笑看君怀她人 2025-01-01 11:50:01

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

我知道我可以通过其他方式实现这一点,例如在上面画我自己的“x”

如果涉及到这一点,那么也许您可以使用 文本图标 类为您进行自定义绘画。

Maybe, as a hack, you can try playing with the left/right inset values and make them non-zero so that the text displays in both LAF's.

I am aware that I can accomplish this in other ways, like painting my own 'x' on top

If it comes to that then maybe you can use the Text Icon class to do the custom painting for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文