0

ソート可能な JTable があります。行が追加されたら、そのビューのインデックスを知りたいです。次のようなテーブルモデルリスナーを使用してみました:

@Override
public void tableChanged(TableModelEvent event)
{
    if (event.getType() == TableModelEvent.INSERT)
    {
        int modelRowIndex = event.getFirstRow();
        int viewRowIndex = table.convertRowIndexToView(modelRowIndex);
        System.out.println("viewRowIndex: " + viewRowIndex);
    }
}

これは、テーブルがソートされていない場合に機能します。残念ながら、テーブルがソートされている場合、変換方法の結果ArrayIndexOutOfBoundsExceptionDefaultRowSorter.java:503.

これは、テーブル モデルが行ソーターに通知する前にリスナーに通知するためだと思います。何か案は?ありがとう!

SSCCE は次のとおりです。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;

public class RowIndexSSCCE extends JFrame
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                new RowIndexSSCCE().setVisible(true);
            }
        });
    }

    private final JTable table;

    public RowIndexSSCCE()
    {
        JButton button = new JButton("Add");
        button.addActionListener(new ButtonListener());

        table = new JTable(new Model());
        table.setAutoCreateRowSorter(true);
        table.getModel().addTableModelListener(new ModelListener());

        JScrollPane scrollPane = new JScrollPane(table);
        JPanel panel = new JPanel();
        panel.add(button);
        panel.add(scrollPane);
        add(panel);
        pack();
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    private class ButtonListener implements ActionListener
    {
        @Override
        public void actionPerformed(ActionEvent event)
        {
            ((Model) table.getModel()).addRow("asdf" + table.getRowCount());
        }
    }

    private class ModelListener implements TableModelListener
    {
        @Override
        public void tableChanged(TableModelEvent event)
        {
            if (event.getType() == TableModelEvent.INSERT)
            {
                int modelRowIndex = event.getFirstRow();
                int viewRowIndex = table.convertRowIndexToView(modelRowIndex);
                System.out.println("viewRowIndex: " + viewRowIndex);
            }
        }
    }

    private class Model extends AbstractTableModel
    {
        private final List<String> data = new ArrayList<String>();

        public void addRow(String string)
        {
            int oldSize = data.size();
            data.add(string);
            fireTableRowsInserted(oldSize, oldSize);
        }

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

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

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

編集:

私は自分でそれを理解しました...使用SwingUtilities.invokeLaterすると、行ソーターが更新された後に行インデックスの変換が確実に行われます:

@Override
public void tableChanged(final TableModelEvent event)
{
    if (event.getType() == TableModelEvent.INSERT)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                int modelRowIndex = event.getFirstRow();
                int viewRowIndex = table.convertRowIndexToView(modelRowIndex);
                System.out.println("viewRowIndex: " + viewRowIndex);
            }
        });
    }
}
4

1 に答える 1