ユーザーがテキストフィールドにテキストを入力すると、KeyPressed イベントで JTextField のサイズを拡張する必要があります。これを実現する方法を教えてください。
前もって感謝します
ユーザーがテキストフィールドにテキストを入力すると、KeyPressed イベントで JTextField のサイズを拡張する必要があります。これを実現する方法を教えてください。
前もって感謝します
さて、それに飛びつきます:-)
質問が
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);
type ... 何も起こりません: size は初期サイズのままです。これは驚きです。何らかの理由で、フィールドの自動検証が行われません。実際、変更通知を受け取ったときにフィールドを手動で再検証しても (注: ここでの唯一の正しいリスナー タイプは 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ドキュメントにあります:
textfield 自体からの revalidate の呼び出しは、textfield が JViewport 内に含まれている場合を除き、textfield を検証することによって処理されます。
言い換えれば、フィールド自体が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 を返します。
私が考えることができる最善の方法は、1つのCaretListenerを関係JTextField
するものに追加することDocument
です.Increase/Decrease
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();
}
});
}
}
1) KeyListener
for JTextComponent
、 use DocumentListener
、他には決して使用しない
FontMetrics
2) 、TextLayout
、を使用できますSwingUtilities
LayoutManager
3) サイズ変更後、通知する必要があります。
4) にのみJTextField
使用する場合pack()
はTop-Level Container
、
JPanel
5)それ以外の場合(ネストされた otherが複数ある場合JComponents
)、コンテナ全体を re_layout しrevalidate()
てrepaint()
から
そのコンテンツで継続的にサイズを変更pack()
する場合は、を呼び出しますTop-Level Container
サイズを変更したくないが、使用が必要な場合は をpack()
呼び出さないでくださいTop-Level Container
JScrollPane
6) 文字列の値が非常に長くなる可能性がある場合JTextComponent
、GUI への複数行出力をサポートする適切な方法を使用するには、プレーンではなくJTextArea
(in ) を使用します。JScrollPane
JTextField
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());
}
});
また、クレオパトラと mKorbel の発言にも注意を払いたいと思います。良いアイデアのように思えるかもしれませKeyListener
んが、通知されない状況が非常に多くあります。これがsetText
主な状況です。