Настройка прослушивателя событий для двух JTextArea

#java #swing #jtextarea #event-listener

#java #swing #jtextarea #прослушиватель событий

Вопрос:

Я разрабатываю программное обеспечение для обработки изображений (просто для развлечения), и одной из его функций является опция изменения размера изображения. В основном появляется окно с двумя JTextArea компонентами для получения желаемой ширины и высоты изображения для изменения размера. Существует также JCheckBox возможность сохранения соотношения сторон, если пользователь этого желает. Проблема в том. Когда флажок установлен, и пользователь предположительно вводит сначала ширину или высоту. Я хочу, чтобы другая текстовая область обновлялась соответствующим образом каждый раз при внесении изменений, чтобы она сохраняла AR. Я разработал некоторый код, который имеет дело с этим, но он не предоставляет то, что я действительно хочу, из-за непонимания того, какой слушатель какому компоненту я должен назначить.

Код:

 String height, width;
  if (checkBoxImage.isSelected()){
      // aspect ratio = width / height
      width = widthArea.getText();
      height = heightArea.getText();
      double aspectRatio = (double) images.get(tabbedPane.getSelectedIndex()).getWidth() / images.get(tabbedPane.getSelectedIndex()).getHeight();
      /**
       * to do, update width, height area
       * to the closest user input
       */
      if(heightArea.getText().length() != 0 amp;amp; heightArea.getText().length() <= 5
              amp;amp; heightArea.getText().charAt(0) != '0'){
          //parsing string to integer
          try{
              int heightNum = Integer.parseInt(height);
              int widthNum = (int) Math.round(aspectRatio * heightNum);
              widthArea.setText(String.valueOf(widthNum) ); 
              widthArea.updateUI();
              frameimgSize.repaint();
          }
          catch(NumberFormatException e1){JOptionPane.showMessageDialog(error,e1.getMessage(),"Error", JOptionPane.ERROR_MESSAGE);} 
      }
      //width has been entered first
      else if(widthArea.getText().length() != 0 amp;amp; widthArea.getText().length() <= 5 amp;amp;
              widthArea.getText().charAt(0) != '0'){
          try{
              int widthNum = Integer.parseInt(width);
              int heightNum = (int) Math.round(aspectRatio * widthNum);
              heightArea.setText(String.valueOf(heightNum) );
              heightArea.updateUI();
              frameimgSize.repaint();
          }
          catch(NumberFormatException e1){JOptionPane.showMessageDialog(error,e1.getMessage(),"Error", JOptionPane.ERROR_MESSAGE);} 
      }
  }
 

Комментарии:

1. Пожалуйста, опубликуйте точный код, с которым у вас возникли проблемы, в самом вопросе, а не в ссылке за пределами сайта. Ваша проблема с установкой текста JTextAreas, или с подключением прослушивателей событий, или с вычислением значений, или с чем-то еще?

2. моя главная проблема заключается в том, к чему именно я должен присоединять прослушиватели событий? Для JTextArea? для компонента CheckBox? Чтобы иметь возможность обновлять текст каждый раз, когда пользователь изменяет значение ширины или высоты JTextArea? на самом деле это не проблема, связанная с кодом.

Ответ №1:

Допустимо ли когда-либо иметь нечисловые значения в ваших полях ширины и высоты?

Если нет, то используйте JSpinners или JFormattedTextFields вместо JTextFields . Если это так (скажем, например, вы разрешаете вводить «единицы измерения», а также ширину и высоту), вам следует прикрепить a DocumentListener к вашим JTextFields, чтобы отслеживать изменения содержимого базовых текстовых документов. Вот пример:

 widthField.getDocument().addDocumentListener(new DocumentListener() {
      public void changedUpdate(DocumentEvent e) {
          update();
      }
      public void removeUpdate(DocumentEvent e) {
          update();
      }
      public void insertUpdate(DocumentEvent e) {
          update();
      }

      // your method that handles any Document change event
      public void update() {
          if( aspectCheckBox1.isSelected() ) {

            // parse the width and height, 
            // constrain the height to the aspect ratio and update it here              
          }
      }

    });            
 

Затем вы бы добавили аналогичный DocumentListener в свое heightTextField.

Обратите внимание, что если вы используете JTextFields, вам необходимо проанализировать их содержимое, прочитать единицы измерения (где это применимо) и обработать исключения NumberFormatExceptions в случае, когда пользователь вводит недопустимые числовые значения.

Чтобы ответить на ваш вопрос о том, куда добавить ваши обработчики…

Обновление ширины должно происходить при изменении документа в элементе графического интерфейса Height. Аналогично обновление высоты должно происходить при изменении документа в элементе GUI Width.

Вам нужно будет корректно обрабатывать ошибки деления на ноль (или ограничивать ввод, чтобы он всегда был больше 0), выполнять вычисления с использованием удвоений и предпочтительно использовать Math.round() для получения наилучших целочисленных значений для сохранения аспекта.

ie:

 int calculateHeight(int width, double aspect) {

    if( aspect <= 0.0 ) {
        // handle this error condition
    }
    return (int)Math.round(width / aspect); 
}
 

Для фактического отслеживания соотношения сторон я бы сохранил его в переменной-члене и добавил ActionListener в JCheckBox … потому что обновление целевого соотношения сторон при каждом изменении значения полей ширины и высоты может привести к «ползучести» соотношения сторон из-за целочисленного округления.

Вот пример отслеживания вашего аспекта при каждом изменении состояния проверки соотношения сторон:

 private double aspect = 1.0;

aspectCheckBox.addActionListener(new java.awt.event.ActionListener() {
    public void actionPerformed(java.awt.event.ActionEvent evt) {
        preserveAspectActionPerformed(evt);
    }
});    

private void preserveAspectActionPerformed(java.awt.event.ActionEvent evt) {                                           

    try {
        double w = Double.parseDouble(widthField.getText());
        double h = Double.parseDouble(heightField.getText());
        aspect = w / h;            
    } 
    catch(NumberFormatException ex) {
        // ... error occurred due to non-numeric input
        // (use a JSpinner or JFormattedTextField to avoid this)
    }
} 
 

Самое главное — избегать использования неправильного типа ввода для задания:

  • JTextArea хороши для многострочного текста
  • JTextFields хороши для однострочного текста
  • JFormattedTextFields хороши для текста, ограниченного определенным форматом
  • JSpinners хороши для ввода чисел.

Надеюсь, это вам поможет.

Ответ №2:

Во-первых, я бы не стал использовать JTextArea , он предназначен для редактирования текста в свободной форме (например, блокнот). Вместо этого вы должны, по крайней мере, использовать a JTextField , но на самом деле a JSpinner может быть даже лучше.

Взгляните на то, как использовать текстовые поля для получения более подробной информации.

По сути, для JTextField вы могли бы использовать a ActionListener и / или a FocusListener для отслеживания изменений в поле.

Эти слушатели, как правило, будут получать уведомления постфактум, то есть только после того, как пользователь закончит редактирование полей. Если вы хотите обратную связь в реальном времени, вы можете использовать a DocumentListener , который будет уведомлять каждый раз, когда изменяется базовая Document часть поля, в режиме реального времени.

A JSpinner немного сложнее, поскольку это компонент, который содержит редактор и элементы управления. Вы можете использовать a ChangeListener , который будет уведомлять о внесении изменений в модель полей. Это происходит вместо ActionListener и FocusListener , упомянутых ранее, поэтому вам должен потребоваться только один прослушиватель, но он не будет предоставлять обратную связь в реальном времени (по крайней мере, не без дополнительной работы)

Комментарии:

1. Спасибо, что за предложения. Я попробую любой из них и посмотрю, как это происходит.