2

经过一番研究,我找到了一种在我的 JTable 中实现公式的方法(如果我理解正确的话,这是一种冗长而乏味的方法。)。

这是表格的样子(您可能会说它是用 netbeans 编辑的,不要介意大量的 null 部分,我们稍后会讨论)

    contractFlaminiaTable.setModel(new javax.swing.table.DefaultTableModel(
        new Object [][] {
            {"name1", null, null, null, null, null, null, null, null, null, null},
            {"name2", null, null, null, null, null, null, null, null, null, null},
            {"name3", null, null, null, null, null, null, null, null, null, null},
            {"name4", null, null, null, null, null, null, null, null, null, null},
            {"name5", null, null, null, null, null, null, null, null, null, null},
            {"name6", null, null, null, null, null, null, null, null, null, null},
            {"name7", null, null, null, null, null, null, null, null, null, null},
            {"name8", null, null, null, null, null, null, null, null, null, null},
            {"TOTAL", null, null, null, null, null, null, null, null, null, null}
        },
        new String [] {
            "  ", "col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8", "col9", "TOTAL"
        }
    ) {
        Class[] types = new Class [] {
            java.lang.String.class, java.lang.Integer.class, java.lang.Integer.class, java.lang.Integer.class, java.lang.Integer.class, java.lang.Integer.class, java.lang.Integer.class, java.lang.Integer.class, java.lang.Integer.class, java.lang.Integer.class, java.lang.Object.class
        };
        boolean[] canEdit = new boolean [] {
            false, true, true, true, true, true, true, true, true, true, false
        };

        public Class getColumnClass(int columnIndex) {
            return types [columnIndex];
        }

        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return canEdit [columnIndex];
        }
    });
    contractFlaminiaTable.setRowHeight(30);
    contractFlaminiaTable.getTableHeader().setReorderingAllowed(false);
    flaminiaScrollPane2.setViewportView(contractFlaminiaTable);
    contractFlaminiaTable.getColumnModel().getColumn(0).setResizable(false);
    contractFlaminiaTable.getColumnModel().getColumn(1).setResizable(false);
    contractFlaminiaTable.getColumnModel().getColumn(2).setResizable(false);
    contractFlaminiaTable.getColumnModel().getColumn(3).setResizable(false);
    contractFlaminiaTable.getColumnModel().getColumn(4).setResizable(false);
    contractFlaminiaTable.getColumnModel().getColumn(5).setResizable(false);
    contractFlaminiaTable.getColumnModel().getColumn(6).setResizable(false);
    contractFlaminiaTable.getColumnModel().getColumn(7).setResizable(false);
    contractFlaminiaTable.getColumnModel().getColumn(8).setResizable(false);
    contractFlaminiaTable.getColumnModel().getColumn(9).setResizable(false);
    contractFlaminiaTable.getColumnModel().getColumn(10).setResizable(false);
    contractFlaminiaTable.getColumnModel().getColumn(10).setPreferredWidth(48);

所以,问题是,在 name1/2/etc 行和列内应该有数字(而不是由 netbeans 自动生成的空垃圾邮件,我在应用程序中有一个“重置”按钮制作自定义 tableModel 但那是一个旧版本,在这里没有用处)并且在总行/列中应该有相应列/行中的数字总和。

从我读过的许多线程中,我可以使用 getValueAt 方法对相应行/列中的单元格求和。不过,我不太确定这是一个不错的选择,因为每次都需要读取大量单元格(它应该在用户在表格中输入数字时动态更新总数,而不是计算我也不知道如何在特定的单元格中实现它)。

以下是问题:

a)是否可以制作一个类似 excel 的公式来添加单元格?(就像添加单元格c2:c6一样,因为我确实将该表导出到一个excel文件中,我想如果这样的事情是可能的......)

2a)我是否必须将列类型更改为对象或所述公式仍将被视为整数?(除了作为 String 类型实现的 name 列之外,所有其他列都是 Integer 类型,最终用户也应该只能插入数字以免弄乱公式,但将类型更改为 Object 实际上可以也插入字母)

b)是否可以在桌子上使用 eventListeners 来制作一个非 excel 式的公式(以防万一 - 这是不可能的)?(类似于“行(x)中的数据,col(y)改变了,用总和更新了总单元格!”)

c)由于表中的数据被导出到 xls 文件(在另一个线程中获得一些指针后已经正确实现),是否可以使用所述文件再次填充表,或者我每次都必须重新绘制它?

很抱歉一起提出所有这些问题(尤其是 c-,因为它与标题无关..)但我并没有真正找到 oracle 提供的 jTable 类教程中的任何内容,也没有在其他类似内容中找到任何建设性的建议线程。

请耐心等待,正如另一个线程中所述,我仍然是一个初学者(如果我可以被认为是一个初学者!)另外,提前感谢您的帮助,另一个中的指针真的帮助了我!

PS:我希望我以一种可以理解的方式解释它,当你必须解释一些东西时,对编程世界的新手并不容易..

再次感谢您的帮助~

编辑:

这是我想出的在表格中实现公式的代码(实际上它是 get/setValueAt() 的一种奇怪用法,但它似乎工作得相当好(有点笨拙但有改进的余地只会让我学到更多东西,这总是一天结束时很好)

class TotalButton {

public TotalButton(JTable jTable) {
    // get table model
    TableModel model = jTable.getModel();

    // declare for variables
    int x;
    int y;

    // initialize table placeholder
    int totalValue = 0;

    int rowCount = model.getRowCount();
    int columnCount = model.getColumnCount();

    // for loop for the first row
    for (x = 0; x < rowCount; x++) {
        for (y = 1; y < columnCount; y++) {
            if (y == 10) {
                break;           // break when the loop reaches the total column
            }
            if (x == 0) {

                String value = (String) model.getValueAt(x, y);
                if ("".equals(value)) {
                    value = "0";            // avoiding empty string to integer error
                }
                int tempVal = Integer.parseInt(value);           // turn the string into a number

                totalValue = totalValue + tempVal;          // adds the numbers to the total
            }
        }

        String finalValue = Integer.toString(totalValue);           // turn the number to a string
        model.setValueAt(finalValue, 0, 10);            // set total column value
    }

基本上我添加了一个按钮来计算和填充表格的总行/列(在某些时候添加了一个 keyListener,但是,正如我所说,它感觉有点笨拙......不是使用按钮感觉有什么不同但很好......) .

您可以在代码段中阅读的循环是为 Total 行/列中的每个单元格添加的(只发布了一部分,因为每个单元格的内容几乎相同)。

还必须在 jTable 模型中用 ""-s 更改 null-s,以便我可以将列类型设置为 String(后来用于 Integer.parseInt() 和 Integer.toString() )。

附带说明一下,虽然 keyListener 感觉有点笨拙,但它会“实时”更新表(说“真实”,因为在表中插入新值不会算作 keyPressed() 直到下一次击键一些原因)。

再次感谢您的指点,该程序似乎工作得相当好,即使它真的可以使用一些代码/逻辑抛光(我目前正在处理)。

PS:我知道这远不是最好的解决方案,但我很高兴,因为我在研究了很多之后自己做了它(当然,如前所述,如果没有指针,我将无法编写代码)

PPS:再次,谢谢你:P

4

2 回答 2

3

对于数字,让您TableModel将表达式存储为String并让您的实现getValueAt()返回表达式的评估结果。有几个可用。

于 2012-09-06T16:12:23.427 回答
0

实际上,对于将 String 转换为 int 的那部分,最好使用 try/catch 块,如果它不能是 int,则将其设为 0。这样,如果您将 Bob、3.1415926 等放入其中,它就可以处理。

于 2013-11-09T17:25:27.617 回答