当用户在textfield中输入文本时,我必须在KeyPressed事件上扩展JTextField的大小。请告诉我如何实现这个目标?
提前致谢
答案 0 :(得分:5)
好的,跳过它: - )
让我们假设问题是
如何调整JTextField的宽度以始终适合其内容宽度?
通常的合作者
快速举例:
JTextField field = new JTextField("something");
JComponent parent = new JPanel(); // has FlowLayout by default
parent.add(field);
frame.add(parent);
// just to ensure it's bigger
frame.setSize(400, 400);
键入...并且没有任何反应:大小保持初始大小。令人惊讶的是:出于某种原因,该领域的自动验证根本不会发生。实际上,在接收更改通知时手动重新验证字段(注意:此处唯一正确的侦听器类型是DocumentListener)也不会更改字段:
final JTextField field = new JTextField("something");
DocumentListener l = new DocumentListener() {
private void updateField(JTextField field)
// has no effect
field.revalidate();
}
@Override
public void removeUpdate(DocumentEvent e) {
updateField(field);
}
@Override
public void insertUpdate(DocumentEvent e) {
updateField(field);
}
@Override
public void changedUpdate(DocumentEvent e) {
}
};
field.getDocument().addDocumentListener(l);
JComponent parent = new JPanel(); // has FlowLayout by default
parent.add(field);
frame.add(parent);
// just to ensure it's bigger
frame.setSize(400, 400);
@Gagandeep Bali发现它是需要重新验证的父:
private void updateField(JTextField field) {
field.getParent().revalidate();
}
出乎意料,所以下一个问题是臭名昭着的为什么?这里:为什么在找到validateRoot之前,容器层次结构中的无效泡沫是什么?答案在api doc中:
来自textfield本身的重新验证调用将通过验证textfield来处理,除非textfield包含在JViewport中,在这种情况下返回false。
或换句话说:它没有冒泡,因为字段本身 是validateRoot。这使得另一个选项覆盖并无条件地返回false:
JTextField field = new JTextField("something") {
@Override
public boolean isValidateRoot() {
return false;
}
};
JComponent parent = new JPanel(); // has FlowLayout by default
parent.add(field);
frame.add(parent);
// just to ensure it's bigger
frame.setSize(400, 400);
为此付出的代价是滚动不起作用 - 在这种情况下这并不重要,因为文本总是适合该领域。或者实现稍微更智能,如果实际宽度小于pref,则返回true。
答案 1 :(得分:3)
我能想到的最好方法是向相关的JTextField
添加一个CaretListener,并且Document
的长度发生变化,Increase/Decrease
通过调用setColumns(...)来表示所述JTextField
的列,其中Increase/Decrease
的大小将JTextField
以下是向您展示如何实现此目标的一个示例:
import java.awt.*;
import javax.swing.*;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
public class JTextFieldColumnExample
{
private int columns = 1;
private JTextField tfield;
private void displayGUI()
{
JFrame frame = new JFrame("JTextField Columns Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel contentPane = new JPanel();
tfield = new JTextField();
tfield.setColumns(columns);
tfield.addCaretListener(new CaretListener()
{
public void caretUpdate(CaretEvent ce)
{
int len = tfield.getDocument().getLength();
if (len > columns)
tfield.setColumns(++columns);
else
{
if (--columns != 0)
tfield.setColumns(columns);
else
{
columns = 1;
tfield.setColumns(columns);
}
}
contentPane.revalidate();
contentPane.repaint();
}
});
contentPane.add(tfield);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new JTextFieldColumnExample().displayGUI();
}
});
}
}
答案 2 :(得分:2)
取决于您是否使用LayoutManager。如果没有,请将KeyListener
附加到JTextField
和keyRelease
,您需要计算字符串的长度(以像素为单位)并确定是否需要更新字段
addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
updateField();
}
public void insertUpdate(DocumentEvent e) {
updateField();
}
public void removeUpdate(DocumentEvent e) {
updateField();
}
public void updateField() {
FontMetrics fm = getFontMetrics(getFont());
String text = getText();
int length = fm.stringWidth(text);
Dimension size = getPreferredSize();
Insets insets = getInsets();
if (length < min) {
size.width = min;
} else {
size.width = length + (insets.left + insets.right);
}
setSize(size);
invalidate();
repaint();
}
});
可能更合理的解决方案可能是:
addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
updateField();
}
public void insertUpdate(DocumentEvent e) {
updateField();
}
public void removeUpdate(DocumentEvent e) {
updateField();
}
public void updateField() {
setColumns(getText().length());
}
});
我也会关注什么是kleopatra&amp; mKorbel不得不说。虽然KeyListener
似乎是一个好主意,但在很多情况下,它不会被通知 - setText
是主要的。
答案 3 :(得分:2)
1)永远不要将KeyListener
用于JTextComponent
,使用DocumentListener
,其他任何内容
2)您可以使用FontMetrics
,TextLayout
,SwingUtilities
3)调整大小后,您必须通知LayoutManager
,
4)如果只有JTextField
,那么pack()
使用Top-Level Container
,
5)否则(如果有多个JPanel
嵌套的其他JComponents
),您必须使用revalidate()
和repaint()
重新布局整个Container } p>
如果您想继续使用其竞争对象调整pack()
,请致电Top-Level Container
如果您不想调整大小,请不要致电pack()
Top-Level Container
,但需要使用JScrollPane
6)如果String的值可能很长,那么使用适当的JTextComponent
支持多行输出到GUI,使用JTextArea
(在JScrollPane
中)比普通JTextField