【问题标题】:How to sum arrays of textfields on the fly in Java如何在 Java 中即时对文本字段数组求和
【发布时间】:2014-04-20 01:03:41
【问题描述】:

我有一些文本字段,我想动态显示其他几个文本字段的总数。我以前从未使用过 Listeners,但经过一些研究后,我发现 DocumentListeners 可能是我正在寻找的。我已经花时间阅读诸如thisthis 之类的低谷相关问题,并且还阅读了java 文档,但我的理解以及我将如何完成我需要做的事情仍然感到不稳定,主要是因为我使用的是 1D 和二维数组。

我想记录 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 并在更新方法中处理不同的类型及其数据?如果后者是可能的,那么实现这一目标的最佳方法是什么?请记住,我是 Listeners 的新手。

【问题讨论】:

    标签: java listener documentlistener


    【解决方案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];
    

    最后,一些初始化和绑定监听器到文本字段的方法:

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

    编辑(根据请求,参见 cmets):初始化代码演练

    注意:我重命名了初始化方法,以便在解释中更容易区分两者。

    初始化代码的总体思路是初始化所有属于同一个方法的字段;即 OT 字段和相应的总字段。这里的观察结果是,对于每个人,每个时间字段(OT1、OT2、ST)的摘要应该是分开的。所以属于一起的字段是时间字段的一维数组和一个总字段;这正是 OvertimeSumListener 中包含的内容。

    initializeAllTimeFields 方法是人员的简单循环,它调用 initializeTimeFields 方法 3 次(每种时间类型一次)为该人员初始化该类型的字段。

    请注意,时间字段被定义为数组数组。所以OT1Field 的类型是JTextField[][]。在循环中,OT1Field[i] 的类型为JTextField[],即内部数组。由于内部数组很容易获得,因此如果内部数组具有“星期几”维度,而外部具有“人员”维度,则代码会大大简化;这就是翻转数组的原因。

    第一种方法initializeAllTimeFields是人员的简单迭代。对于每次迭代(即每个人员),为三种时间类型中的每一种调用第二种方法。

    第二种方法,initializeTimeFields 将“星期几”的数组用于一个人和一个时间类型。数组值用新的JTextField 对象初始化,并返回一个新的JTextField 对象作为总数。它还创建一个新的OvertimeSumListener 并将其添加到每个数组元素(但不是总数)。

    此方法的签名旨在简化代码。由于java中的数组是作为对象引用传递的,所以当修改initializeTimeFields中的一维数组时,会修改原始数组的内容。此外,在此方法中创建和初始化总计字段的新对象,并返回结果总计对象,以便可以将总计数组的正确数组元素分配给该值。

    【讨论】:

    • 感谢您的回答,抱歉耽搁了,但您知道……圣帕蒂节周末。我一直在花时间研究您的答案并在我的程序中使用您的建议。让我困惑的是它怎么可能有“totalOT1Field[i] = initializeOTTextFields(OT1Field[i]);”当 OT1Field 是二维数组时,在 initializeOTTextFields() 中。您是否只是为了说明和想法而进行概括?或者这在 Java 中是否被接受,如果是的话,你能把它分解成进一步的解释吗?再次感谢您的出色回答。
    • @solleks :这不仅仅是一个想法的说明,它是工作代码(我在发布之前对其进行了测试)。我将通过进一步解释其工作原理来更新答案。我还编写了一些额外的代码来显示文本字段,以便我可以测试代码,但选择从答案中省略它,因为它与问题的重点无关。
    • 非常感谢,这正是我需要看到的。我剩下的唯一小问题是如果添加文本然后从时间字段中删除,总字段显示为空白。我假设应该在 removeUpdate() 中处理。我会自己解决这个问题,但如果你想再上一节课,我会全神贯注哈哈。感谢您的帮助。
    猜你喜欢
    • 2013-06-28
    • 2021-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-11
    • 1970-01-01
    • 2010-12-05
    • 1970-01-01
    相关资源
    最近更新 更多