我必须为用户在keyPressed事件扩大JTextField的大小进入textfield.please文字给我一些想法如何实现这一目标?
提前致谢
我必须为用户在keyPressed事件扩大JTextField的大小进入textfield.please文字给我一些想法如何实现这一目标?
提前致谢
好吧,跳吧:-)
让我们假设问题是
如何调整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);
键入......却没有任何反应:尺寸保持在初始大小。 这是惊喜:由于某种原因,该字段的自动验证简单doesnt't发生。 事实上,该领域在接收到变更通知手动重新验证(注:只有正确键入侦听这里是一个的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巴厘岛发现,这是一个需要重新验证父 :
private void updateField(JTextField field) {
field.getParent().revalidate();
}
意外的,所以接下来的问题是臭名昭著的,为什么 ? 在这里:为什么不无效泡了容器层次结构,直到它找到一个validateRoot添加? 答案是在API文档:
呼吁重新验证的是来自文本字段本身内将通过验证文本字段,除非文本字段包含在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);
为此付出的代价,是滚动不工作 - 这是不是一个大问题,在这种背景下,作为文本总是适合进入该领域。 或者稍微更智能实现,而如果实际宽度小于把选项返回true。
我能想到的最好的办法是一个加CaretListener到JTextField
关注,并与在长度的变化Document
,你Increase/Decrease
的说,列JTextField
通过调用它的setColumns(...) ,这inturn将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();
}
});
}
}
1) never to use KeyListener
for JTextComponent
, use DocumentListener
, nothing else
2) you can to use FontMetrics
, TextLayout
, SwingUtilities
3) after resize you have to notify LayoutManager
,
4) if is there only JTextField
then to use pack()
for Top-Level Container
,
5) otherwise (in the case that there is more than one JPanel
nested other JComponents
) you have to re_layout whole Container with revalidate()
and repaint()
then
call pack()
to the Top-Level Container
if you want to resize continiously with its contens
don't call pack()
to the Top-Level Container
if you don't want to resize, but required usage of JScrollPane
6) in the case that value of String could be very long, then to use proper JTextComponent
with supporting multiline output to the GUI, to use JTextArea
(in JScrollPane
) rather than plain JTextField
取决于如果您使用的是布局管理与否。 如果没有,附加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());
}
});
我还要注意些什么克列奥帕特拉&mKorbel不得不说。 虽然KeyListener
似乎是一个不错的主意,有正义的许多情况的,它不会被通知- setText
是主要的一个。