2016-08-14 4 views
0

Я работаю над небольшим проектом (с Java Builder Builder NetBeans), в котором у меня есть 100 TextFields, который делает то же самое по разным данным. Они расположены в 10 строк и 10 столбцов, там (Переменные) имена подобны:Java Swing, 100 TextFields имеют схожую задачу, поэтому я хочу написать одну функцию для этого

txt11, txt12, ... txt110 
txt21, txt22, ... txt210 
    .  .  ... . 
txt101, txt102, ... txt1010 

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

Поскольку они выполняют аналогичную задачу я могу написать один метод, который принимаетстроки и Col в качестве аргументов и получить выполняется всякий раз, когда пользователь пишет что-то в любом из TextField. Чтобы выполнить эту задачу, я должен выяснить строку и столбец, к которым они принадлежат.

Я пытался использовать следующий код внутри обработчика событий (я добавил же слушателя событий для всех JTextField):

private void TextFieldAnswerTyped(java.awt.event.KeyEvent evt) { 
    String name = ((JTextField)evt.getSource()).getName(); 

    int row,col; 
    if(name.endsWith("10")) 
    { 
     col=10; 
     name=name.substring(0, name.length()-2); 
    } 
    else 
    { 
     col=Integer.parseInt(name.substring(name.length()-1,name.length())); 
     name=name.substring(0, name.length()-1); 
    } 

    if(name.endsWith("10")) 
     row=10; 
    else 
     row=Integer.parseInt(name.substring(name.length()-1,name.length())); 

    checkForCell(row, col); //Performs the task 
} 

Everytime событие встречается, это дает мне null как name. Я делаю какую-либо ошибку здесь или есть хорошая альтернатива.

+1

Вы смотрите на ненужную работу для себя. Почему бы не объединить все это и просто использовать JTable? –

+0

Возможно, вы путаете поле имени, которое получается путем вызова 'getName()', с именем переменной, что-то совершенно другое. Если вы не можете использовать JTable (опять моя основная рекомендация), тогда поместите все ваши JTextFields в двумерный массив и выполните итерацию по массиву, чтобы получить позицию столбца и строки. –

+2

Любой дизайн (программное обеспечение, а также пользовательский интерфейс), который требует от вас (или ваших пользователей) работы со 100 текстовыми полями, просто: ** сломан **. Сделайте так, как предлагает судно на воздушной подушке; и A) рассмотреть возможность использования другого компонента пользовательского интерфейса и B) узнать о массивах или что-то еще. Именование переменных a1, a2, ... и т. Д .; а затем использовать имя, чтобы сделать отражение назад, чтобы идентифицировать что-то ... действительно очень плохая идея. Серьезно: так происходит «кошмары обслуживания». – GhostCat

ответ

3

Ваша проблема в том, что вы путаете имя переменной с полем имени JTextField. Вызов getName() на JTextField возвращает последнее, его поле имени, которое, как вы выяснили, по умолчанию задано как null. Несколько решений представляют собой:

  • Вы можете попытаться использовать отражение, чтобы получить объект, к которому относится переменная, которую вы интересуете, - плохая, хрупкая и глухая идея - просто не делайте этого.
  • Вы можете фактически установить имя поля, чтобы быть таким же, как имя переменной, по телефону setName(...) на JTextField после его создания - еще один плохой кладж
  • Лучше бы разместить все объекты JTextField в 1 или 2 мерного массива или коллекции. Таким образом, было бы легко узнать, в какой строке и столбце находится ваше поле.
  • Возможно, лучшим решением (трудно сказать, не зная большего требования) было бы использование JTable, один с 10 строками и 10 столбцами ,

Ваш вопрос звучит так, как будто это может быть XY Problem, где вы спрашиваете «как исправить этот код», когда реальное решение полностью использует другой подход. Пожалуйста, расскажите нам больше о своем «проблемном пространстве» - какую общую проблему вы пытаетесь решить, так как снова я думаю, что для вас, вероятно, будет лучшее решение.


Другой вопрос: Вы, кажется, пытается использовать KeyListener с JTextFields, то я не рекомендую, так как это может повлиять на текстовые поля родной обработки ключей. Вместо этого вы почти всегда лучше используете DocumentListener или DocumentFilter.


Другой вариант, чтобы установить метод свинг компонент, putClientProperty(...), чтобы ваши текстовых полей JTextField «знают», что строка и столбец они в. Примером этого, который использует вышеупомянутый метод плюс это добытчик эквивалент, и который использует ActionListener в JTextField, чтобы получить данные следующим образом:

import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.*; 

@SuppressWarnings("serial") 
public class ManyFields extends JPanel { 

    private static final int ROWS = 10; 
    private static final int COLS = ROWS; 
    private static final int GAP = 2; 
    private static final int TF_COLS = 5; 
    public static final String ROW = "row"; 
    public static final String COL = "col"; 
    private JTextField[][] fieldGrid = new JTextField[ROWS][COLS]; 

    public ManyFields() { 
     setLayout(new GridLayout(ROWS, COLS, GAP, GAP)); 
     setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP)); 

     TFieldListener tFieldListener = new TFieldListener(); 

     for (int row = 0; row < fieldGrid.length; row++) { 
      for (int col = 0; col < fieldGrid[row].length; col++) { 
       JTextField tField = new JTextField(TF_COLS); 
       tField.putClientProperty(ROW, row); 
       tField.putClientProperty(COL, col); 
       tField.addActionListener(tFieldListener); 

       add(tField); 
       fieldGrid[row][col] = tField; 
      } 
     } 
    } 

    private class TFieldListener implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      JTextField field = (JTextField) e.getSource(); 
      int row = (int) field.getClientProperty(ROW); 
      int col = (int) field.getClientProperty(COL); 

      // or another way to get row and column using the array: 
      int row2 = -1; 
      int col2 = -1; 
      for (int r = 0; r < fieldGrid.length; r++) { 
       for (int c = 0; c < fieldGrid[r].length; c++) { 
        if (field == fieldGrid[r][c]) { 
         row2 = r; 
         col2 = c; 
        } 
       } 
      } 
      // now here row2 and col2 are set 

      String text = field.getText(); 

      String title = String.format("Text for Cell [%d, %d]", col, row); 
      String message = "text: " + text; 
      int messageType = JOptionPane.INFORMATION_MESSAGE; 
      JOptionPane.showMessageDialog(ManyFields.this, message, title, messageType); 
      field.transferFocus(); // move to next component 
     } 
    } 

    private static void createAndShowGui() { 
     ManyFields mainPanel = new ManyFields(); 

     JFrame frame = new JFrame("Many Fields"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
} 

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

+0

Спасибо @ HovercraftFullOfEel для ** putClientProperty **. Следующий ответ также помог мне в поиске компонентов по названию http://stackoverflow.com/questions/4958600/get-a-swing-component-by-name#17806100 обе вместе решили мою проблему. –