2012-07-30 4 views
0

Мне нужно расширить размер JTextField при событии KeyPressed, когда пользователь вводит текст в текстовое поле. Попробуйте дать мне некоторое представление о том, как достичь этого?изменить размер JTextField на KeyPress

заранее спасибо

+4

Пожалуйста, объясните, что вы _really_ хотите достичь - keyPress не обязательно запускается, когда пользователь вводит текст (fi при вставке) – kleopatra

ответ

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 & mKorbel должен сказать. Хотя KeyListener может показаться хорошей идеей, есть только ко многим ситуациям, где он не будет уведомлен - setText является основным.

+0

нет ... и вы его знаете ;-) – kleopatra

+0

@kleopatra 'подбрасывает руки в воздухе' На этот раз я наделал ошибку :( – MadProgrammer

+0

направляя новичков в совершенно неправильное направление, что еще ;-) – kleopatra

2

1) никогда не использовать KeyListener для JTextComponent, используйте DocumentListener, больше ничего

2) вы можете использовать FontMetrics, TextLayout, SwingUtilities

3) после изменения размера вы должны уведомить LayoutManager,

4) если есть только JTextField, то использовать pack() для Top-Level Container,

5) в противном случае (в том случае, если есть больше чем один JPanel вложенных другой JComponents) вы должны re_layout всего контейнера с revalidate() и repaint() затем

  • вызова pack() к Top-Level Container, если вы хотите изменить размер продолжительного с его

    оглавлению
  • не называют pack() к Top-Level Container, если вы не хотите, чтобы изменить размер, но требуется использование JScrollPane

6) в случае, если значение строки может быть очень длинным, а затем использовать надлежащий JTextComponent с поддержкой многострочного вывода в графический интерфейс, чтобы использовать JTextAreaJScrollPane), а не простой JTextField

+0

Я бы не согласился (в этот случай) о 'KeyListener'. Если бы мы манипулировали текстом, абсолютно, используйте DocumentListener. Простите, мне любопытно, почему почему вы предлагаете это (я, возможно, не знаю, что вы делаете;)). Однако я согласен с пунктом 6! – MadProgrammer

+0

@MadProgrammer все :-) описано в 1-й точке, там было бы плохим утешением, что JTextField имеет фокус и принимает, что JTextField имеет мышь, фокус, каретку и клавиатуру, причем оба ответа здесь охватывают только один кватер :-), то я оставляю комментарии для голосования, например в этой теме .... – mKorbel

+0

arggghhh ... эти длинные списки пулей снова ... 1) хорошо 2) не нужно 3) нет 4) возможно, но не вероятно 5) нет, за исключением, возможно, переопределения верхнего уровня контейнер 6) хорошо. Это значение: отношение шума 2: 4;) – kleopatra

3

Лучший способа я может думать о том, чтобы добавить один 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(); 
      } 
     }); 
    } 
} 
+0

Нет, вам нужно установить столбец, просто добавив его в FlowLayout, не увеличит его область просмотра, хотя вы можете добавить к нему материал. Но для того, чтобы увеличить область просмотра, вам нужно обновить значение Column, на этот раз это действительно несправедливо, чтобы уменьшить это :( –

+1

doohhh ...вы правы, был _sure_ Я видел, что самовосстанавливаюсь, извините – kleopatra

+0

еще более странно: revalidate на _parent_ действительно нужен (хотя и не перекраска, afaics) BTW: caretListener не то, что вы хотите - это не обязательно стрельба , fi нет, если вставка происходит в позиции> caretPosition – kleopatra

5

Хорошо, прыгая за это :-)

Давайте предположим, что речь идет о

Как настроить JTextField-х ширину, чтобы всегда соответствовать ширине его содержимого?

Обычные сотрудники

  • LayoutManager размеры которого своих детей в их прив размер, F.I. FlowLayout
  • 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); 

типа ... и ничего не происходит: размер остается на первоначальном размере. Это удивительно: по какой-то причине авто-валидация поля просто не происходит.На самом деле, руководство REVALIDATE поля на получение уведомления об изменении (Примечание: только правильный слушатель типа здесь является 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? Ответ в апи документе:

призывает перепроверить, которые приходят из самих текстового поля будет обрабатываться путем проверки текстового поля, если текстовое поле не содержатся в JViewport, в этом случае это возвращает ложь.

Или другими словами: это не пузырились потому, что само поле является validateRoot. Что оставляет другой вариант, чтобы переопределить и безоговорочно вернуть ложь:

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

Это, без сомнения, имеет более глубокое понимание :-) –

+0

+1 для расширенного объяснения – MadProgrammer

+0

+1 для обладания нулевым размером и +1 для повторного открытия isValidateRoot для мне (кажется, периодически появляющаяся, экзотическая информация API, которая вам не нужна, если вы ее знаете, и не знаете, когда она вам понадобится). (doh, все еще нет +1 +1 возможно :() – TheBlastOne

Смежные вопросы