这就是用户想要的:如果文本太长而无法容纳文本字段,请将其设置为工具提示。否则,应该没有工具提示。
问题:Swing 没有告诉我们它是否修剪了字段的文本。没有这样的属性,不会触发任何事件。
为了简单起见,请忘记工具提示。只需让打印消失即可(请参阅 MRE)。基本上,我需要“听”修剪/表演。
这是 MRE。更改窗口的大小以影响字段的宽度。
package demos.text.formattedTextField;
import javax.swing.JFormattedTextField;
import javax.swing.JPanel;
import javax.swing.text.DefaultFormatter;
import javax.swing.text.DefaultFormatterFactory;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.LayoutManager;
import java.text.ParseException;
public class FormattedTextFieldDemo {
public static void main(String[] args) {
Container mainPanel = createMainPanel();
JFrame frame = new JFrame("FormattableTextField Demo");
frame.setContentPane(mainPanel);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private static JPanel createMainPanel() {
LayoutManager layout = new GridBagLayout();
JPanel panel = new JPanel(layout);
panel.add(createFormattedTextField(), constraints());
return panel;
}
private static GridBagConstraints constraints() {
GridBagConstraints constraints = new GridBagConstraints();
constraints.weightx = 1;
constraints.fill = GridBagConstraints.BOTH;
return constraints;
}
private static JFormattedTextField createFormattedTextField() {
JFormattedTextField textField = new JFormattedTextField();
DefaultFormatterFactory formatterFactory = new DefaultFormatterFactory();
formatterFactory.setDisplayFormatter(new DefaultFormatter() {
@Override
public String valueToString(Object value) throws ParseException {
return value instanceof Cat ? ((Cat) value).getName() : super.valueToString(value);
}
});
textField.setFormatterFactory(formatterFactory);
textField.setValue(createFormattedValue());
return textField;
}
private static Cat createFormattedValue() {
Cat cat = new Cat("mew".repeat(10));
return cat;
}
private static void onTextTrim() {
System.out.println("Text has been trimmed...");
}
private static void onTextShow() {
System.out.println("Text is now fully displayed...");
}
static class Cat {
private final String name;
public Cat(String name) {
this.name = name;
}
@Override
public String toString() {
return super.toString();
}
public String getName() {
return name;
}
}
}
这是 GPT 的建议,虽然可行,但在我看来很难看
textField.addComponentListener(new ComponentAdapter() {
private boolean isTrimmed = false;
@Override
public void componentResized(ComponentEvent e) {
checkTextTrim(textField);
}
@Override
public void componentShown(ComponentEvent e) {
checkTextTrim(textField);
}
private void checkTextTrim(JFormattedTextField field) {
FontMetrics metrics = field.getFontMetrics(field.getFont());
String text = field.getText();
int textWidth = metrics.stringWidth(text);
int fieldWidth = field.getWidth();
boolean currentlyTrimmed = textWidth > fieldWidth;
if (currentlyTrimmed && !isTrimmed) {
isTrimmed = true;
onTextTrim();
} else if (!currentlyTrimmed && isTrimmed) {
isTrimmed = false;
onTextShow();
}
}
});
我不认为在条件改变时打印消息会让任务变得更容易。当我们仅在满足显示工具提示的先决条件(即当鼠标光标悬停在组件上或用户明确按下 control + f1 时)时检查条件时,要做的工作就更少了。
例如,您可以简单地更换线路
JFormattedTextField textField = new JFormattedTextField();
与
JFormattedTextField textField = new JFormattedTextField() {
// needed because we have no static ToolTipText
{ ToolTipManager.sharedInstance().registerComponent(this); }
@Override
public String getToolTipText() {
return getPreferredSize().width > getWidth()? getText(): null;
}
};
要模仿某些外观的行为,直接在文本上显示剪切文本的工具提示,您可以添加
@Override
public Point getToolTipLocation(MouseEvent event) {
return new Point(0, 0);
}
此组件。