繁体   English   中英

知道为什么 AbstractTableModel 会导致将空单元格添加到我的表格中吗? (Java 摆动)

[英]Any idea why AbstractTableModel causes empty cells to be added to my table? (Java Swing)

正如标题所说,当我向底层列表添加内容时,空单元格被添加到我的表格中。

主要类:

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

主框架类:

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

有没有更好的方法从我的一维数组中获取项目,以便从左到右、从上到下填充表格(没有额外的空单元格)?

为什么会出现这个问题?

结果: 添加了额外的空行。

strings.add("data"); 

你应该使用类似的东西:

strings.add("data" + i); 

所以每个单元格中的值是不同的。 通过这种方式,您可以判断数据是否正确显示。

每当向列表中添加内容时,都会使用 fireTableDataChanged() 动态更新列表。

那是错的。 fireTableDataChanged() 方法只能由 TableModel 内部的方法调用。 一旦创建了 TableModel,您就忘记了 ArrayList 并调用 TableModel 上的一个方法来更新 ArrayList。

所以你需要在你的 TableModel 中添加一个像addItem(…)这样的addItem(…) 然后 TableModel 将更新 ArrayList,然后调用fireTableRowsInserted(…) (如果您有奇数个项目)或fireTableRowsUpdated(…) (如果您有偶数个项目)。

就像是:

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

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

您拥有的数据和您对其建模的方式是两个不同的关注点,不要害怕将它们分开以实现您的目标,例如:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM