Java Swing, 100 TextFields have similar task, So I want to write the one function to do so

风流意气都作罢 提交于 2019-12-12 03:52:40

问题


I am working on a small project (with NetBeans' Java GUI Builder) in which I have 100 TextFields which does exact same thing on different data. They are arranged in 10 rows and 10 columns, there (Variable) names are like:

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

so, that there names can easily generated by the row and column number as well as I can easily extract the row and the column of a TextField to which it belongs (But I can not).

Since they perform similar task I can write a single method which takes row and col as arguments and get executed whenever user writes something in any of the TextField. In order to accomplish the task I have to find out the row and the column they belong.

I tried to use following code inside the event listener ( I have added same event listener for all 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 the event occures it gives me null as the name. Am I doing any mistake here or Is there any good alternative.


回答1:


Your problem is that you're confusing the variable name with the JTextField's name field. Calling getName() on the JTextField returns the latter, its name field, which as you're finding out is set by default to null. Several solutions present themselves:

  • You could try to use reflection to get the object that the variable you're interested in refers to -- a bad, brittle and kludgy idea -- just don't do it.
  • You could in fact set the name field to be the same as the variable name, by calling setName(...) on the JTextField after creating it -- another bad kludge
  • Better would be to place all your JTextField objects into a 1 or 2 dimensional array or collection. By doing this, it would be easy to find out which row and column your field is in.
  • Perhaps the best solution (hard to tell without knowing more requirements) would be to use a JTable, one with 10 rows and 10 columns.

Your question sounds like it may in fact be an XY Problem where you ask "how do I fix this code" when the real solution is to use a different approach entirely. Please do tell us more about your "problem space" -- what overall problem that you're trying to solve, since again I think that there likely is a better solution out there for you.


Another issue: you appear to be trying to use a KeyListener with JTextFields, something I also do not recommend as this can interfere with the text fields native key processing. Instead you're almost always better off using a DocumentListener or a DocumentFilter.


Another option is to set the Swing component method, putClientProperty(...), to have your JTextFields "know" which row and column they're in. An example of this which uses the above method plus it's getter equivalent, and which uses an ActionListener in the JTextField to get the data is as follows:

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());
    }
}

But again, likely a JTable would offer a better solution, however it's hard to know exactly how to create this without more requirement information.



来源:https://stackoverflow.com/questions/38943066/java-swing-100-textfields-have-similar-task-so-i-want-to-write-the-one-functio

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!