任何想法,为什么AbstractTableModel都会导致将空单元格添加到我的表中? (Java Swing)

问题描述 投票:0回答:2

正如标题所说,当我向基础列表中添加内容时,会将空单元格添加到我的表中。

主类:

import javax.swing.SwingUtilities;

public class Main {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                MainFrame frame = new MainFrame();
            }
        });
    }
}

MainFrame类:

import java.awt.BorderLayout;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JTable;

public class MainFrame extends JFrame {
    private JTable table;
    private ArrayList<String> strings;

    public MainFrame() {
        setTitle("Stack Overflow");
        setSize(800, 800);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());
        setVisible(true);

        strings = new ArrayList<String>();
        table = new JTable(new TableModel(strings));

        add(table,BorderLayout.CENTER);

        for (int i = 0; i < 10; i++) {
            strings.add("data");
        }
    }
}

AbstractTableModel类:

import java.util.List;

import javax.swing.table.AbstractTableModel;

public class TableModel extends AbstractTableModel {
    private String[] colNames = {"Col1","Col2"};

    private List<String> strings;

    public TableModel(List<String> strings) {
        this.strings = strings;
    }

    @Override
    public String getColumnName(int column) {
        return colNames[column];
    }

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

    @Override
    public int getColumnCount() {
        return 2;
    }

    @Override
    public String getValueAt(int rowIndex, int columnIndex) {
        if (rowIndex*2 + columnIndex >= strings.size()) return "";
        return strings.get(rowIndex*2 + columnIndex);
    }
}

是否有更好的方法来从我的1D数组中获取项目,以便从左到右,从上到下(没有多余的空单元格)填充表格?

为什么仍然会发生此问题?

结果:Extra empty rows added.

java swing jtable abstracttablemodel
2个回答
0
投票
strings.add("data"); 

您应该使用类似:

strings.add("data" + i); 

所以每个单元格中的值都不同。这样,您可以判断数据是否正确显示。

只要将内容添加到列表,该列表就会使用fireTableDataChanged()动态更新。

错了。 fireTableDataChanged()方法只能由TableModel内部的方法调用。一旦创建了TableModel,您就不用理会ArrayList并在TableModel上调用一个方法来更新ArrayList。

因此您需要在TableModel中添加类似addItem(…)的方法。然后,TableModel将更新ArrayList,如果项数为奇数,则调用fireTableRowsInserted(…),如果项数为偶数,则调用fireTableRowsUpdated(…)

类似:

public void addItem(String item)
{
    strings.add( item );

    if (string.size() % 2 == 0)
        fireTableRowsUpdated(…);
    else
        fireTableRowsInserted(…);
}

0
投票

您拥有的数据和建模方式是两个不同的问题,不要害怕将它们分开来实现您的目标,例如:

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.Timer;
import javax.swing.table.AbstractTableModel;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JTable table;
        private SequentialTableModel model;

        public TestPane() {
            setLayout(new BorderLayout());
            model = new SequentialTableModel();
            table = new JTable(model);
            add(new JScrollPane(table));

            Timer timer = new Timer(500, new ActionListener() {
                private int count = 0;
                @Override
                public void actionPerformed(ActionEvent e) {
                    model.add("Data " + (++count));
                }
            });
            timer.start();
        }

    }

    public class SequentialTableModel extends AbstractTableModel {

        private String[] colNames = {"Col1", "Col2"};

        private List<List<String>> rows = new ArrayList<>(32);

        public SequentialTableModel() {
        }

        @Override
        public String getColumnName(int column) {
            return colNames[column];
        }

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

        @Override
        public int getColumnCount() {
            return 2;
        }

        @Override
        public String getValueAt(int rowIndex, int columnIndex) {
            List<String> values = rows.get(rowIndex);
            if (columnIndex >= values.size()) {
                return null;
            }
            return values.get(columnIndex);
        }

        public void add(String value) {
            if (rows.isEmpty()) {
                addNewRow(value);
                return;
            }

            List<String> lastRow = rows.get(rows.size() - 1);
            if (lastRow.size() < 2) {
                lastRow.add(value);
                fireTableCellUpdated(rows.size() - 1, lastRow.size() - 1);
            } else {
                addNewRow(value);
            }
        }

        protected void addNewRow(String value) {
            List<String> row = new ArrayList<>(2);
            row.add(value);
            rows.add(row);
            fireTableRowsInserted(rows.size() - 1, rows.size() - 1);
            return;
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.