2015-04-23 3 views
1

У меня есть JTextArea, что я хочу, чтобы пользователь вводил адрес человека. Я знаю, что действительный адрес, который вводит пользователь, не будет превышать 5 rows и 10 columns. Поэтому я установил его в JTextArea (5,10). Таким образом, он отлично работает.Отключение изменения JTextArea при нажатии пользователем Enter

Проблема заключается в том, что если пользователь продолжает нажимать enter больше, чем 5 раз, область текста начнет изменяться. Я не хочу помещать текстовую область в JScrollPane, так как текст, который вводит пользователь, не очень похож на прокрутку.

Вопрос: Как мы отключаем JTextArea изменение размера, когда пользователь нажимает кнопку enter?

Вот мой код:

public class JTextAreaDemo { 

private JFrame frame; 

JTextAreaDemo(){ 
    frame= new JFrame(); 
    frame.setSize(300, 300); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setLayout(new net.miginfocom.swing.MigLayout()); 
    frame.setVisible(true); 
    frame.setLocationRelativeTo(null); 

    JLabel label=new JLabel("Address :"); 
    JTextArea address= new JTextArea(5,20); 
    frame.add(label,"cell 0 0"); 
    frame.add(address, "cell 1 0"); 
} 

public static void main(String [] args){ 
    SwingUtilities.invokeLater(new Runnable(){ 

     @Override 
     public void run() { 
      new JTextAreaDemo(); 

     }}); 
    } 
} 
+1

Поместите его в 'JScrollPane', он изменит размер, потому что он предпочитает размер меняется – MadProgrammer

+0

Вы хотите сказать, что когда пользователь нажимает кнопку ввода в 5-й раз, он будет либо заменен пробелом, либо проигнорирован? – Blip

+0

@MadProgrammer Ну, это работает. Одна вещь. Как мне избежать перемещения курсора на шестую строку/строку, когда пользователь нажимает клавишу ввода? – JWizard

ответ

2

Вы можете попробовать использовать DocumentFilter, например:

import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.text.AbstractDocument; 
import javax.swing.text.AttributeSet; 
import javax.swing.text.BadLocationException; 
import javax.swing.text.DocumentFilter; 

public class TestFrame extends JFrame { 

    public static void main(String... s) { 
     new TestFrame(); 
    } 

    private JTextArea area; 

    public TestFrame() { 
     init(); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     pack(); 
     setLocationRelativeTo(null); 
     setVisible(true); 
    } 


    private void init() { 
     area = new JTextArea(); 
     ((AbstractDocument)area.getDocument()).setDocumentFilter(getFilter(5)); 
     add(new JScrollPane(area)); 
    } 

    private DocumentFilter getFilter(final int lineCount) { 
     return new DocumentFilter(){ 

      @Override 
      public void replace(FilterBypass fb, int offset, int length, 
        String text, AttributeSet attrs) 
        throws BadLocationException { 
       if(area.getLineCount()<=lineCount && area.getLineOfOffset(area.getCaretPosition())<lineCount) 
         if(text.contains("\n") && area.getLineCount()<lineCount) 
          super.replace(fb, offset, length, text, attrs); 
         else if(!text.contains("\n")) 
          super.replace(fb, offset, length, text, attrs); 
      } 
     }; 
    } 

} 
+0

Ну, это на самом деле то, что я искал, учитывая ограничение количества строк/строк. Это так много. – JWizard

+0

@Giovanrich добро пожаловать – alex2410

+0

Как правило, фильтр не должен знать о текстовом компоненте, он вроде бы побеждает цель. – MadProgrammer

1

Использование setPreferredSize(new Dimension(X,Y)) так что JTextArea сохранит размер вы устанавливаете, и привычка двигаться на всех! Вам нужно будет поместить ваш JTextArea внутри мысли JScrollPane.

+0

Ну, установив предпочтительный размер рядом с использованием' JScrollPane'. Установка предпочтительного размера сама по себе не могла это сделать, в любом случае спасибо за наконечник. – JWizard

+0

@Giovanrich Добро пожаловать, я отредактировал свой ответ на ваш ответ, не забудьте закрыть свой вопрос, когда закончите. – Mekap

+0

JTextArea и MigLayout ненавидит setPreferredSize, это о переносе строки/слова для JTextArea внутри JScrollPane, иначе .... :-) – mKorbel

0

Я бы предположил, что вы должны использовать InputVerifier, который будет отслеживать количество входящих, введенных в ваш JTextArea, и когда он достигнет 4, тогда он должен игнорировать входящие.

Как вы указали в ваших комментариях DocumentListener будет делать то же самое, а также KeyListener может сделать то же самое.

+0

Разве 'InputVerifer 'не получает уведомление о фокусе? Это не остановит пользователя переполнения поля текстом, когда поле установлено на обертку, например – MadProgrammer

+0

@MadProgrammer Как насчет 'DocumentListener'? - Не спасает ли цель отслеживания? – JWizard

+0

@MadProgrammer Я действительно забыл, что ** Да, это правда **, и я исправляю свой ответ, чтобы приспособиться к этому. – Blip

2

Как уже говорилось, DocumentFilter могут быть использованы. Я отправляю этот ответ из-за элегантного решения, которое он предлагает.

public class JTextAreaDemo { 

    private JFrame frame = new JFrame(); 
    JTextArea address = new JTextArea(5, 20); 

    JTextAreaDemo() { 

     JLabel label = new JLabel("Address :"); 
     frame.getContentPane().add(label, BorderLayout.CENTER); 
     frame.getContentPane().add(address, BorderLayout.SOUTH); 

     ((PlainDocument) address.getDocument()).setDocumentFilter(new LineFilter()); 

     frame.pack(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    class LineFilter extends DocumentFilter { 

     @Override 
     public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException { 

      if (address.getLineCount() < 5 || !string.contains("\n")) 
       super.insertString(fb, offset, string, attr); 
     } 

     @Override 
     public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException { 

      if (address.getLineCount() < 5 || !text.contains("\n")) 
       super.replace(fb, offset, length, text, attrs); 
     } 
    } 

    public static void main(String[] args) { 

     new JTextAreaDemo(); 
    } 
} 

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

Обратите внимание, что нет необходимости в JScrollBar.

Edit:

Чтобы @MadProgrammer спать спокойно по ночам, счетная линия делается (в менее изящным способом) непосредственно из документа:

@Override 
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException { 

    String content = fb.getDocument().getText(0, fb.getDocument().getLength()); 
    Matcher matcher = Pattern.compile("\n").matcher(content); 
    int lines = 0; 
    while (matcher.find()) { 
     lines++; 
    } 
    if (lines < 4 || !text.contains("\n")) 
     super.replace(fb, offset, length, text, attrs); 
} 

Метод insertString может используйте тот же код.

+0

Общее правило большого пальца, фильтр не должен знать о компоненте пользовательского интерфейса/текста, который его использует. Предполагая, что в текстовой области нет включенной обертки строк, это становится относительно легким делом ... если не ... – MadProgrammer

+0

@MadProgrammer Я полностью согласен с эмпирическим правилом, хотя, когда содержимое (сторона документа) влияет на визуализации (сторона компонента пользовательского интерфейса), я думаю, что для этого есть заслуга. Я добавил решение, удобное для правил. – user1803551

+0

В случае переноса строки это вам не поможет. Изучите [это] (http://stackoverflow.com/questions/12837605/how-to-take-line-wrap-in-account-for-jtextarea-line-counting) – alex2410