Любая идея, почему AbstractTableModel вызывает добавление пустых ячеек в мою таблицу? (Java качели) - PullRequest
0 голосов
/ 19 марта 2020

Как видно из заголовка, в мою таблицу добавляются пустые ячейки, когда я что-то добавляю в базовый список.

Основной класс:

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 Class:

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.

Ответы [ 2 ]

1 голос
/ 19 марта 2020

Имеющиеся у вас данные и способ их моделирования - это две разные задачи, не бойтесь разделять их для достижения ваших целей, например:

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;
        }
    }
}
1 голос
/ 19 марта 2020
strings.add("data"); 

Вы должны использовать что-то вроде:

strings.add("data" + i); 

, поэтому значение в каждой ячейке отличается. Таким образом, вы можете определить, правильно ли отображаются данные.

Список обновляется динамически с помощью fireTableDataChanged () всякий раз, когда что-то добавляется в список.

Это неправильно. Метод fireTableDataChanged () должен всегда вызываться только методом внутри TableModel. После создания TableModel вы забываете о ArrayList и вызываете метод TableModel для обновления ArrayList.

Так что вам нужно добавить метод, подобный addItem(…), к вашей TableModel. Затем TableModel обновит ArrayList и затем вызовет либо fireTableRowsInserted(…), если у вас нечетное количество элементов, либо fireTableRowsUpdated(…), если у вас четное количество элементов.

Что-то вроде:

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

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