2012-01-06 82 views
2

我已经创建了一个文本字段组件,其中带有一个“x”按钮,用于清除该字段的文本。当使用Window的系统外观和感觉(对于Windows)时,它非常适用,但是在使用Nimbus时我试图获得正确的外观,即我无法像使用系统一样使用button.setMargin(new Inset(0, 0, 0, 0)更改按钮上的边距外观和感觉。如何覆盖单个按钮的Nimbus按钮边距

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

我明确地设置了'x'按钮的大小,它是从'x'字符串的边界计算出来的,以便它显示出'x'的大小。

结果使用Windows的系统的外观和感觉,这就是我要找的整体外观时:使用默认的Nimbus外观时

System look and feel

结果; 'x'溢出Nimbus允许的空间,导致省略号。使用雨云并重写Button.contentMargins时

Nimbus look and feel

结果:现在的“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'按钮的文本框),我可以使用它。

+1

虽然我不能与你的问题的帮助,该功能是太酷了:d GL与修复! – Ari 2012-01-07 05:12:48

回答

7

雨云支持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); 
+0

感谢您的回答;这就是我寻找的结果。我的'x'按钮现在至少可以在三种外观(Mac,Windows和Nimbus)中很好地显示。 – purplecat 2012-01-09 19:14:40

2

您可以使用其中一种较小尺寸的变体,然后让按钮显示其首选大小,以保证文本有空间吗?

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

+0

我尝试了迷你尺寸,但按钮仍然包含比我想要的文字更多的空间,而'x'太小了。但是知道我可以调整这样的组件以供将来参考是有帮助的。 – purplecat 2012-01-09 19:12:19

1

也许,作为一个黑客,你可以尝试用左/右inset值玩,使他们不为零,使文本显示在两个LAF的。

我知道,我可以用其他方式做到这一点,像画我自己的“X”在上面

如果它来的那么也许你可以使用Text Icon类做定制为你画画。

+0

如果您建议更改如下所示的插入:'mButton.setMargin(new Insets(0,10,0,10));',它不适用于Nimbus,因为它会覆盖具有其默认值的任何设置边距值。 – purplecat 2012-01-09 19:20:39