我有文本字段,我希望能够动态显示其他几个文本字段。我之前从未使用过Listeners,但经过一些研究后发现DocumentListeners可能就是我想要的。我花了很多时间阅读相关的问题,例如this和this,并且还阅读了java文档,但我的理解仍然感到不稳定以及我将如何完成我需要做的事情,主要是因为我我正在使用一维和二维阵列。
我想记录10个工人在一周中每天工作的3种不同类型的时间(直线时间,加班时间和双加时时间)以及总数。
为此,我创建了这些变量:
private static final int NUMBER_OF_PERSONNEL = 10;
private static final int DAYS_OF_THE_WEEK = 7;
private JTextField OT2Field[][] = new JTextField[DAYS_OF_THE_WEEK][NUMBER_OF_PERSONNEL];
private JTextField OT1Field[][] = new JTextField[DAYS_OF_THE_WEEK][NUMBER_OF_PERSONNEL];
private JTextField STField[][] = new JTextField[DAYS_OF_THE_WEEK][NUMBER_OF_PERSONNEL];
private JTextField totalOT2Field[] = new JTextField [NUMBER_OF_PERSONNEL];
private JTextField totalOT1Field[] = new JTextField [NUMBER_OF_PERSONNEL];
private JTextField totalSTField[] = new JTextField [NUMBER_OF_PERSONNEL];
因此,OT2Field [0] [0]到OT2Field [6] [0]将= totalOT2Field [0]
我是否需要为每种类型的工作时间使用DocumentListener?或者,我可以拥有一个DocumentListener并在更新方法中处理不同类型及其数据吗?如果后者是可能的,那么最好的方法是什么呢?请记住,请记住,我是听众的新手。
答案 0 :(得分:1)
解决此问题的一种简单方法是编写一个实现DocumentListener
的类,它知道应该汇总哪些文本字段以及需要更新的总文本字段。
在下面的实现中,我只假设OT表示为十进制数。
public class OvertimeSumListener implements DocumentListener {
private JTextField[] otFields;
private JTextField total;
public OvertimeSumListener(JTextField[] otFields, JTextField total) {
this.otFields = otFields;
this.total = total;
}
public void calculateTotal() {
double sum = 0;
for (JTextField otField : otFields) {
String text = otField.getText();
try {
sum += Double.parseDouble(text);
} catch (NumberFormatException e) {
// not a number - ignore
}
}
total.setText(String.format("%.2f", sum));
}
public void insertUpdate(DocumentEvent e) {
calculateTotal();
}
public void removeUpdate(DocumentEvent e) {
calculateTotal();
}
public void changedUpdate(DocumentEvent e) {
calculateTotal();
}
}
初始化侦听器并将它们绑定到文本字段时,如果将2D数组从[DAYS_OF_THE_WEEK][NUMBER_OF_PERSONNEL]
翻转到[NUMBER_OF_PERSONNEL][DAYS_OF_THE_WEEK]
,则会更容易,例如:
private JTextField OT2Field[][] = new JTextField[NUMBER_OF_PERSONNEL][DAYS_OF_THE_WEEK];
private JTextField OT1Field[][] = new JTextField[NUMBER_OF_PERSONNEL][DAYS_OF_THE_WEEK];
private JTextField STField[][] = new JTextField[NUMBER_OF_PERSONNEL][DAYS_OF_THE_WEEK];
最后,有些方法可以初始化并将侦听器绑定到textfields:
private void initializeAllTimeFields() {
for (int i = 0; i < NUMBER_OF_PERSONNEL; i++) {
totalOT1Field[i] = initializeTimeFields(OT1Field[i]);
totalOT2Field[i] = initializeTimeFields(OT2Field[i]);
totalSTField[i] = initializeTimeFields(STField[i]);
}
}
private JTextField initializeTimeFields(JTextField[] timeFields) {
JTextField totalField = new JTextField();
totalField.setEditable(false);
OvertimeSumListener listener = new OvertimeSumListener(timeFields, totalField);
for (int i = 0; i < timeFields.length; i++) {
timeFields[i] = new JTextField();
timeFields[i].getDocument().addDocumentListener(listener);
}
return totalField;
}
编辑(根据请求,请参阅注释):初始化代码的演练
注意:我重命名了初始化方法,以便更容易区分两者。
初始化代码的一般思想是初始化同一方法中属于一起的所有字段;即OT字段和相应的总字段。这里的观察是对于每个时间字段(OT1,OT2,ST)的每个人和,摘要应该是分开的。因此,属于一起的字段是一维时间字段数组和一个总字段;这正是OvertimeSumListener
中包含的内容。
initializeAllTimeFields
方法是对调用initializeTimeFields
方法三次(每种时间类型一次)的人员的简单循环,以初始化该人的该类型的字段。
请注意,时间字段定义为数组数组。因此OT1Field
的类型为JTextField[][]
。在循环中,OT1Field[i]
的类型是JTextField[]
,即内部数组。由于获取内部数组非常容易,如果内部数组具有“星期几”维度且外部具有“人员”维度,则代码将大大简化;这就是翻转阵列的原因。
第一种方法initializeAllTimeFields
是人员的简单迭代。对于每次迭代(即每个人员),为三种时间类型中的每一种调用第二种方法。
第二种方法initializeTimeFields
采用一个人和一次类型的“星期几”数组。使用新的JTextField
对象初始化数组值,并返回总数的新JTextField
对象。它还会创建一个新的OvertimeSumListener
并将其添加到每个数组元素(但不是总数)。
此方法的签名旨在简化代码。由于java中的数组作为对象引用传递,因此在对initializeTimeFields
中的单维数组进行修改时,将修改原始数组的内容。此外,在该方法中创建并初始化总字段的新对象,并返回所得到的总对象,以便可以将总数组的正确数组元素分配给该值。