是否可以在JTable中监听指定列的数据更改?

时间:2016-01-03 12:07:52

标签: java swing jtable listener stack-overflow

我正在使用一种类似excel的公式来处理JTable,因为有些单元格是自动计算的。

我使用TableModelListener来监听数据更改,并调用一个函数来遍历所有数据并计算每行的值,如下所示。

我计算列号3" uds",它包含一个由colum片段给出的整数。例如,如果片段的值为" 3" uds应为" 1"或者如果片段的值为" 3-5" uds应该是" 2"

private void maths() {
        //    0        1       2     3      4
        // Descrip - Pieces - PVP - Uds - Total - Done
        //                          Col 4 is Nº of "-"  (col2 * col3)
        int colDescrip = 0; int colPieces = 1; int colPvp = 2;  int colUds = 3; int colTotal = 4; //Columnas

        for(int row = 0; row < getTable().getRowCount(); row++) {

            String pieces = getTable().getModel().getValueAt(row, colPiezas).toString();

            if(pieces != "") {
                Integer n = nOfHyphens(getTable().getModel().getValueAt(row, colPieces).toString());
                System.out.println(n);
                getTable().getModel().setValueAt(n, row, colUds); //Error here
            }


            System.out.println("Col 0: " + getTable().getModel().getValueAt(row, 0) + "." + getTable().getModel().getValueAt(row, 0).getClass());
            System.out.println("Col 1: " + getTable().getModel().getValueAt(row, 1) + "." + getTable().getModel().getValueAt(row, 1).getClass());
            System.out.println("Col 2: " + getTable().getModel().getValueAt(row, 2) + "." + getTable().getModel().getValueAt(row, 2).getClass());
            System.out.println("Col 3: " + getTable().getModel().getValueAt(row, 3) + "." + getTable().getModel().getValueAt(row, 3).getClass());
            System.out.println("Col 4: " + getTable().getModel().getValueAt(row, 4) + "." + getTable().getModel().getValueAt(row, 4).getClass());
            System.out.println("#################");
        }

    }

    private int nOfHyphens(String s) {
        int t = 1;
        char c = '-';
        for(int i = 0; i < s.length(); i++) 
            if(s.charAt(i) == c) 
                t++;

        return t;
    }

这个maths()函数在public void tableChanged(TableModelEvent arg0)内调用,我的问题是每次计算每行的总数时,数据会发生变化,当然事件会一次又一次地调用,直到我得到StackOverflowError,我该如何防止这种情况发生?制作一个带有数据的JTable和带有结果的另一个JTable?或者只有在指定的列发生变化时才能调用此事件?

感谢。

编辑:添加完整代码

public class PresupuestoFrameNuevo extends JFrame{

    private JPanel tableHolder;
    private JPanel btnHolder;
    private JPanel btnleft;
    private JPanel btnright;

    private JScrollPane jsp;
    private JTable table;

    private JButton addrow;
    private JButton delrow;
    private JButton save;
    private JButton cancel;

    private ButtonListener BL;
    private TableListener TL;

    public static void main(String args[]) {
        new PresupuestoFrameNuevo();
    }

    public PresupuestoFrameNuevo() {
        setSize(1000,600);
        setTitle("Presupuesto nuevo");
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setLocationRelativeTo(null);
        setLayout(new BorderLayout());

        initComps();
        drawComps();

        setVisible(true);
    }

    private void initComps() {

        setTable(new JTable(new PresupuestoModel()));
        setJsp(new JScrollPane(getTable()));

        getTable().getTableHeader().setReorderingAllowed(false);
        getTable().getTableHeader().setResizingAllowed(false);
        getTable().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        getTable().setCellSelectionEnabled(true);   

        setTL(new TableListener());

        getTable().getModel().addTableModelListener(getTL());

        //Table width
        getTable().getColumnModel().getColumn(0).setPreferredWidth(300); //Descrip
        getTable().getColumnModel().getColumn(2).setMaxWidth(80);//pvp unidad
        getTable().getColumnModel().getColumn(3).setMaxWidth(70);//unidades
        getTable().getColumnModel().getColumn(4).setMaxWidth(80);//total
        getTable().getColumnModel().getColumn(5).setMaxWidth(60);//hecho

        setTableHolder(new JPanel());
        setBtnHolder(new JPanel());
        setBtnleft(new JPanel());
        setBtnright(new JPanel());

        getTableHolder().setLayout(new GridLayout(1,1));
        getBtnHolder().setLayout(new GridLayout(1,2));

        setBL(new ButtonListener());

        setAddrow(new JButton("Add row"));
        setDelrow(new JButton("Delete row")); //TODO
        setSave(new JButton("Save"));         //TODO
        setCancel(new JButton("Cancel"));     //TODO

        getAddrow().addActionListener(getBL());
        getDelrow().addActionListener(getBL());
        getSave().addActionListener(getBL());
        getCancel().addActionListener(getBL());

    }

    private void drawComps() {

        getBtnleft().add(getAddrow());
        getBtnleft().add(getDelrow());
        getBtnright().add(getSave());
        getBtnright().add(getCancel());

        getBtnleft().setBorder(BorderFactory.createTitledBorder("Tools"));
        getBtnright().setBorder(BorderFactory.createTitledBorder("Options"));
        getTableHolder().add(getJsp());
        getBtnHolder().add(getBtnleft());
        getBtnHolder().add(getBtnright());

        add(getBtnHolder(), BorderLayout.SOUTH);
        add(getTableHolder(), BorderLayout.CENTER);
    }

    private class ButtonListener implements ActionListener{

        @Override
        public void actionPerformed(ActionEvent ae) {
            if(ae.getSource() == addrow) {
                ((PresupuestoModel) getTable().getModel()).addRow();
            }
            else if(ae.getSource() == delrow) {

            }
            else if(ae.getSource() == save) {

            }
            else if(ae.getSource() == cancel) {

            }

        }

    }

    private class TableListener implements TableModelListener{

        @Override
        public void tableChanged(TableModelEvent e) {
            System.out.println(e.getSource());
            System.out.println(e.getSource().getClass());
            System.out.println(e.getColumn());

            /*if(e.getColumn() == 3) {
                return;
            }
            else {

                //maths();  
            }*/


        }

        private void maths() {
            //    0        1          2           3         4
            // Descrip - Piezas - PVP Unidad - Unidades - Total - Hecho
            //                                  Nº of "-"  2*3
            int colDescrip = 0; int colPieces = 1; int colPvp = 2;  int colUds = 3; int colTotal = 4; //Columnas

            for(int row = 0; row < getTable().getRowCount(); row++) {

                String pie = getTable().getModel().getValueAt(row, colPieces).toString();

                if(pie != "") {
                    Integer n = nOfHyphens(getTable().getModel().getValueAt(row, colPieces).toString());
                    System.out.println(n);
                    getTable().getModel().setValueAt(n, row, colUds);
                }


                System.out.println("Col 0: " + getTable().getModel().getValueAt(row, 0) + "." + getTable().getModel().getValueAt(row, 0).getClass());
                System.out.println("Col 1: " + getTable().getModel().getValueAt(row, 1) + "." + getTable().getModel().getValueAt(row, 1).getClass());
                System.out.println("Col 2: " + getTable().getModel().getValueAt(row, 2) + "." + getTable().getModel().getValueAt(row, 2).getClass());
                System.out.println("Col 3: " + getTable().getModel().getValueAt(row, 3) + "." + getTable().getModel().getValueAt(row, 3).getClass());
                System.out.println("Col 4: " + getTable().getModel().getValueAt(row, 4) + "." + getTable().getModel().getValueAt(row, 4).getClass());
                System.out.println("#################");
            }

        }

        private int nOfHyphens(String s) {
            int t = 1;
            char c = '-';
            for(int i = 0; i < s.length(); i++) 
                if(s.charAt(i) == c) 
                    t++;

            return t;
        }

    }

    public JPanel getTableHolder() {
        return tableHolder;
    }

    public void setTableHolder(JPanel tableHolder) {
        this.tableHolder = tableHolder;
    }

    public JPanel getBtnHolder() {
        return btnHolder;
    }

    public void setBtnHolder(JPanel btnHolder) {
        this.btnHolder = btnHolder;
    }

    public JPanel getBtnleft() {
        return btnleft;
    }

    public void setBtnleft(JPanel btnleft) {
        this.btnleft = btnleft;
    }

    public JPanel getBtnright() {
        return btnright;
    }

    public void setBtnright(JPanel btnright) {
        this.btnright = btnright;
    }

    public JScrollPane getJsp() {
        return jsp;
    }

    public void setJsp(JScrollPane jsp) {
        this.jsp = jsp;
    }

    public JTable getTable() {
        return table;
    }

    public void setTable(JTable table) {
        this.table = table;
    }

    public JButton getAddrow() {
        return addrow;
    }

    public void setAddrow(JButton addrow) {
        this.addrow = addrow;
    }

    public JButton getDelrow() {
        return delrow;
    }

    public void setDelrow(JButton delrow) {
        this.delrow = delrow;
    }

    public JButton getSave() {
        return save;
    }

    public void setSave(JButton save) {
        this.save = save;
    }

    public JButton getCancel() {
        return cancel;
    }

    public void setCancel(JButton cancel) {
        this.cancel = cancel;
    }

    public ButtonListener getBL() {
        return BL;
    }

    public void setBL(ButtonListener bL) {
        BL = bL;
    }

    public TableListener getTL() {
        return TL;
    }

    public void setTL(TableListener tL) {
        TL = tL;
    }



}

的TableModel

public class PresupuestoModel extends AbstractTableModel {

    private String[] cols = { "Description", "Pieces", "PVP U", "Uds", "Total", "Done" };
    private Vector<Object[]> data;

    public PresupuestoModel() {
        setData(new Vector<Object[]>());
    }

    public void addRow() {
        Object[] s = new Object[getCols().length];

        for (int i = 0; i < getCols().length; i++) {
            if (i != getCols().length - 1)
                s[i] = "";
            else
                s[i] = new Boolean(false);
        }

        getData().add(s);
        fireTableRowsInserted(getRowCount() - 1, getColumnCount());
    }

    public void deleteRow(int index) {
        getData().remove(index);
        fireTableRowsDeleted(index, index);
    }

    public String getColumnName(int n) {
        return getCols()[n];
    }

    public boolean isCellEditable(int row, int col) {
        if ((col == 3) || (col == 4)) 
            return false;
        else 
            return true;
    }

    public Class<?> getColumnClass(int c) {
        if (c == getCols().length - 1) {
            return Boolean.class;
        }
        else if((c == 2) || (c == 3)) {
            return Integer.class;
        }
        else { 
            return String.class;
        }
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        return (getData().get(rowIndex))[columnIndex];
    }

    public void setValueAt(Object value, int row, int col) {
        System.out.println("Object: " + value + "." + value.getClass()+ "[" + row + "," + col + "]");
        if(col == getCols().length - 1) {
            (getData().get(row))[col] = value;
        }
        else if((col > 1) || (col < 5))  {
            (getData().get(row))[col] = value;
        }
        else {
            (getData().get(row))[col] = value.toString();
        }
        fireTableDataChanged();
    }

    @Override
    public int getColumnCount() {
        return getCols().length;
    }

    @Override
    public int getRowCount() {
        return getData().size();
    }

    public String[] getCols() {
        return cols;
    }

    public void setCols(String[] cols) {
        this.cols = cols;
    }

    public Vector<Object[]> getData() {
        return data;
    }

    public void setData(Vector<Object[]> data) {
        this.data = data;
    }

}

1 个答案:

答案 0 :(得分:4)

TableModelEvent参数有一个getColumn()方法,它将告诉您正在更改的列并导致该事件。您可以使用if块,检查此方法返回的int,如果忽略了列,只需调用return;

public void tableChanged(TableModelEvent event) {
    if (event.getColumn() == COLUMN_TO_IGNORE) {
        return;
    } else {
        maths();
    }
}