我创建了一个文本字段组件,里面有一个“x”按钮,用于清除字段的文本。使用Window的系统外观(适用于Windows)时效果很好,但是在使用Nimbus时尝试获得正确的外观时遇到问题 - 即我无法使用button.setMargin(new Inset(0, 0, 0, 0)
更改按钮上的边距可以与系统的外观和感觉。
在使用Nimbus时,我确实寻求设置边距的帮助,这似乎是一个常见的问题。我能够找到允许我更改边距的部分解决方案,但是它会更改所有按钮的边距,我只希望单个按钮与默认值不同。
我明确地设置'x'按钮大小,根据'x'字符串的边界计算,这样它就足以显示'x'。
使用Window的系统外观时的结果,这是我正在寻找的一般外观:
使用默认Nimbus外观时的结果; 'x'溢出了Nimbus允许的空间,导致省略号。
使用Nimbus并覆盖Button.contentMargins的结果:现在'x'按钮看起来正确,但'test'按钮看起来很糟糕。
源代码:
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的边距,并且感觉没有更改所有按钮的边距。或者,如果已经存在看起来相似的摆动组件(带有“x”按钮的文本字段),我可以使用它。
答案 0 :(得分:7)
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);
答案 1 :(得分:2)
您可以使用其中一个较小尺寸的变体,然后让按钮以其首选尺寸显示,以确保文本的空间?
http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/size.html
答案 2 :(得分:1)
也许,作为一个黑客,你可以尝试使用左/右插入值并使它们非零,以便文本显示在两个LAF中。
我知道我可以通过其他方式实现这一点,比如画我自己的' x'在顶部
如果是这样,那么也许你可以使用Text Icon类为你做自定义绘画。