我有一个包含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);
}
}
}
}
答案 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上一个数字的元素。可以通过您获得的循环来完成。
原来,该问题源于大量使用的实例字段而不是局部变量。由于代码仅部分发布,因此很难仅凭问题来确定代码。