从JFrame中动态创建的变量获取数据

时间:2019-06-15 08:32:13

标签: java variables dynamic jframe jtextfield

我有一个包含Jspinner的Jframe。当增加JSpinner时,将在我的面板headerPanel中创建一个新的JTextField。该脚本会在文本框的变量名(tFrame0,tFrame1等)上附加一个整数。

原始代码和所有旧修改内容已移至This粘贴框。

链接pastebin以防万一将来对任何人都有帮助,并且不会弄乱当前相关的代码。

这在TreffnonX的帮助下得以解决!感谢您在评论和聊天中对我非常耐心。

这是工作代码,以防以后有人偶然发现此类问题。

全局变量

private JPanel headerPanel;
private JSpinner spinner;

public List<JTextField> findTextFields() {
    List<JTextField> fields = new LinkedList<>();

    Component[] children = headerPanel.getComponents();
    for (Component child : children) {
        if (child instanceof JTextField) {
            JTextField childField = (JTextField) child;

            // check, if the name is prefixed correctly.
            String name = childField.getName();
            if (name.startsWith(nameTField)) {
                fields.add(childField);
            }
        }
    }

    return fields;
}

JSpinner

spinner = new JSpinner();
spinner.setModel(new SpinnerNumberModel(1, 1, 100, 1));
    spinner.addContainerListener(new ContainerAdapter() {
    @Override
    public void componentAdded(ContainerEvent arg0) {
        adaptBoxes();
    }
});
spinner.addChangeListener(new ChangeListener() {
    public void stateChanged(ChangeEvent arg0) {
        int spinnerValue = (Integer) spinner.getValue();
        if (spinnerValue == headerPanel.getComponentCount()) {
            System.out.println("Error, spinner shouldn't change to same alue");
        }
        adaptBoxes();
        frame.revalidate();
        frame.repaint();
    }
});
adaptBoxes();

adaptBoxes();方法

public void adaptBoxes() {
    // Find value of spinner.
    int spinnerValue = (Integer) spinner.getValue();

    List<JTextField> textFields = findTextFields();
    int numTextFields = textFields.size();

    if (numTextFields > spinnerValue) {
        // if we have too many fields.
        for (JTextField textField : textFields) {
            String name = textField.getName();
            Matcher matcher = POSTFIX_PATTERN.matcher(name);
            if (matcher.matches()) {
                String strPostfix = matcher.group(1);
                int postFixNumeric = Integer.parseInt(strPostfix);

                System.out.println("for postFix = " + postFixNumeric + ": " + textField.getText());
                if (postFixNumeric >= spinnerValue) {
                    System.out.println("PFN: " + postFixNumeric);
                    System.out.println("FTF: " + numTextFields);
                    headerPanel.remove(textField);
                }
            }
        }
    } else {
        while (numTextFields < spinnerValue) {
            // if we have too few fields.
            int hp = headerPanel.getComponentCount();

            JTextField tField = new JTextField();
            tField.setName(nameTField + hp);

            tField.getDocument().addDocumentListener(new TextFieldDocumentListener());

            headerPanel.add(tField);

            textFields = findTextFields();
            numTextFields = textFields.size();
        }
    }
}

JTextField文档侦听器

/**
 * Inner class
 */
private final class TextFieldDocumentListener implements DocumentListener {
    @Override
    public void changedUpdate(DocumentEvent e) {
        warn();
    }

    @Override
    public void removeUpdate(DocumentEvent e) {
        warn();
    }

    @Override
    public void insertUpdate(DocumentEvent e) {
        warn();
    }

    /**
     * Actual sysout to inform the user...
     */
    public void warn() {
        List<JTextField> textFields = findTextFields();
        for (JTextField textField : textFields) {
            String name = textField.getName();

            Matcher matcher = POSTFIX_PATTERN.matcher(name);
            System.out.println(name);

            if (matcher.matches()) {
                String strPostfix = matcher.group(1);
                int postfixNumeric = Integer.parseInt(strPostfix);

                System.out.println("for postfix = " + postfixNumeric + ": " + textField.getText());
            } else {
                System.out.println("matcher error: " + matcher);
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

除非您要使用反射(https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/package-summary.html),否则不能将“ for循环int i追加到变量名”。通过反射,您可以搜索java-Object的字段,并根据其名称(如果公开)访问它们。

幸运的是,这实际上不是您真正需要的。您实际上是在寻找一种通过类型和名称来标识J?Panel的子级(Component)的方法,然后推断出以前附加的索引。我的建议是执行以下操作:

// This pattern can be anywhere in the Class-file:
public static final Pattern POSTFIX_PATTERN = Pattern.compile("tFrame(\\d+)");

// This should be in your exposed GUI class (supposedly the Panel), but can be anywhere it can access headerPanel.
public List<JTextField> findTextFields() {
    List<JTextField> fields = new LinkedList<>();

    Component[] children = headerPanel.getComponents();
    // this is your 'search-loop':
    for (Component child : children) {
        if (child instanceof JTextField) {
            JTextField childField = (JTextField) child;
            String name = childField.getName();
            if (name.startsWith("tFrame")) {
                fields.add(childField);
            }
        }
    }

    return fields;
}

(也可以使用Stream来完成,但是上面的代码更简单)。

上面的代码“找到”您现有的组件,您可以从那里进行工作,例如,根据它们的名称对它们进行排序,然后进行打印。

为什么只收到部分文本字段的问题似乎对修改有反应,是因为您(可能)没有将相同的inputData数组传递给创建的不同DocumentListener 。如果设置断点并检查,我敢打赌inputData-Arrays具有不同的哈希值。就是说,由于周围的代码不完整,我无法推断出这100%。

我建议更改:

if (tField.getText() != null) {
    Object[] currentData = new Object[getFieldNum + 1];
    currentData[getFieldNum] = tField.getText();

    inputData[getFieldNum] = tField.getText();

    for (int i = 0; i < inputData.length; i++) {
        if (inputData[i] != null) {
            System.out.println("for i = " + i + ": " + inputData[i]);
        }

    }
}

for (JTextField textField : findTextFields()) {
    String name = textField.getName();
    Matcher matcher = POSTFIX_PATTERN.matcher(name);
    if (matcher.matches()) {
        String strPostfix = matcher.group(1);
        int postfixNumeric = Integer.parseInt(strPostfix);

        System.out.println("for postfix = " + postfixNumeric + ": " + textField.getText());
    }
}

这样,您就可以在用户实际做出要响应的更改的时间点获得组件。

还附带说明: 一旦减少或增加JSpinner上的数字,您是否真的要替换所有现有的文本字段及其当前状态?

也许可以考虑删除postfixNumeric >= getTextFields().size()的元素,或者增加元素的数量而不删除小于JSpinner上一个数字的元素。可以通过您获得的循环来完成。

编辑

原来,该问题源于大量使用的实例字段而不是局部变量。由于代码仅部分发布,因此很难仅凭问题来确定代码。