Java Swing, 100 TextFields有类似的任务,所以我想写一个函数来做到这一点



我正在做一个小项目(与NetBeans' Java GUI Builder),其中我有100个TextFields,在不同的数据上做完全相同的事情。它们按10行10列排列,其中(变量)名称如下:

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

所以,有名字可以很容易地生成的行和列号,以及我可以很容易地提取的行和列的TextField,它属于(但我不能)。

由于它们执行类似的任务,我可以编写一个方法,该方法将rowcol作为参数,并在用户在任何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
}

每次事件发生,它给我null作为name

是我写错了吗?

您的问题是将变量名称与JTextField的名称字段混淆了。在JTextField上调用getName()返回后者,它的名称字段,正如您所发现的,默认情况下设置为null。有几个解决方案:

  • 你可以尝试使用反射来获得你感兴趣的变量所指向的对象——这是一个糟糕的、脆弱的、笨拙的想法——只是不要这样做。
  • 实际上,您可以设置名称字段与变量名称相同,通过在创建JTextField后调用setName(...) -另一个坏的kludge
  • 最好将所有JTextField对象放入1或2维数组或集合中。通过这样做,可以很容易地找到您的字段所在的行和列。也许最好的解决方案(在不了解更多需求的情况下很难判断)是使用JTable,一个有10行10列的JTable。

你的问题听起来可能实际上是一个XY问题,你问"我如何修复这个代码",而真正的解决方案是使用完全不同的方法。请告诉我们更多关于你的"问题空间"——你试图解决的总体问题是什么,因为我再次认为可能有一个更好的解决方案适合你。


另一个问题:您似乎试图使用KeyListener与JTextFields,我也不建议,因为这可能会干扰文本字段的本地键处理。相反,你最好使用DocumentListener或DocumentFilter。


另一个选项是设置Swing组件方法putClientProperty(...),让JTextFields"知道"它们位于哪一行和哪一列。这个例子使用了上面的方法加上等价的getter,并在JTextField中使用ActionListener来获取数据,如下所示:

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可能会提供更好的解决方案,但是如果没有更多的需求信息,很难确切地知道如何创建它。

相关内容

  • 没有找到相关文章

最新更新