当前位置: 首页 > 知识库问答 >
问题:

FireTables结构更改后,如何在JTable中维护用户指定的表行排序?

郑宜民
2023-03-14

方法fireTableStructureChanged()从头开始重新绘制整个JTable。众所周知,用户指定的列宽和用户指定的行排序(当用户单击其中一个列标题时)将丢失。

有没有办法存储自定义排序并在调用fireTableStructureChanged()后将其检索回来?可能是方法convertRowIndexToModelconvertRowIndexToView可以帮助。。。

或者是否有另一种方法可以在保留排序的情况下重新绘制整个表(在更改行计数后)?

下面是我添加/删除一些行的实验的简短示例:

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.table.AbstractTableModel;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;


public class Table extends JFrame {

    private static final long serialVersionUID = 1L;

    private JTable table;

    private String[][] tableData = {{"a", "5"},
                                    {"b", "4"},
                                    {"c", "9"},
                                    {"d", "2"},
                                    {"e", "1"},
                                    {"f", "7"},
                                    {"g", "3"},
                                    {"h", "8"},
                                    {"i", "6"}};

    private String[] columns = {"A", "B"};

    public Table() {
        MyTableModel mtm = new MyTableModel(tableData, columns);
        this.setLayout(new BorderLayout());
        table = new JTable(mtm);
        table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        table.getTableHeader().setReorderingAllowed(false);
        table.setCellSelectionEnabled(true);
        table.setAutoCreateRowSorter(true);                     

        JScrollPane scrollpane = new JScrollPane(table);
        scrollpane.setPreferredSize(new Dimension(600, 150));
        this.add(scrollpane);
        this.setLocation(300, 100);
        setVisible(true);
        pack();

        //Trying to add and remove some rows:
        mtm.addRow(new Object[]{"new 1", "new 2"});
        mtm.removeRow(2);
        mtm.removeRow(3);
        table.addNotify();
    }

    public class MyTableModel extends AbstractTableModel {

        private static final long serialVersionUID = 1L;

        private String[][] tableData;

        private String[] columns;

        public MyTableModel(String[][] tableData, String[] columns) {
            this.tableData = tableData;
            this.columns = columns;
        }

        public void addRow(Object newRow) {
             fireTableRowsInserted(2, 2);
        }

        public void removeRow(int row) {
            fireTableRowsDeleted(row, row);
        }

        public int getRowCount() {
            return tableData.length;
        }

        public int getColumnCount() {
            return columns.length;
        }

        public String getColumnName(int column) {
            return columns[column];
        }

        public Object getValueAt(int row, int col) {
            return tableData[row][col];
        }

        public void setValueAt(Object value, int row, int col) {
            String oldValue = (String) tableData[row][col];
            if(oldValue.equals((String)value)) {
                return;
            }
            tableData[row][col] = value.toString();
        }

        public boolean isCellEditable(int row, int col) {
            return true;
        }
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                new Table();

            }
        });
    }
}

共有1个答案

麹正业
2023-03-14

根据AbstractTableModel#fireTableStructureChanged()javadoc:

通知所有侦听器表的结构已更改。表中的列数以及新列的名称和类型可能与以前的状态不同。如果JTable接收到此事件,并设置了其autoCreateColumnsFromModel标志,则会丢弃其拥有的所有表列,并按照默认列在模型中的显示顺序重新分配默认列。这与在JTable上调用setModel(TableModel)相同。

因此,如果调用此方法,则保持列宽(因为可能已更改)或行排序或筛选(数据也可能已更改)没有意义。

或者是否有另一种方法可以在保留排序的情况下重新绘制整个表(在更改行计数后)?

如果要在行插入/删除中更新表数据,则需要在表模型中提供此类方法,并在此类事件中通知TableModelListener:

class MyTableModel extends AbstractTableModel {
    ...
    public void addRow(Object newRow) {
        // add row to underlying data structure here
         fireTableRowsInserted(rowIndex, rowIndex);
    }

    public void remove(Object rowToBeDeleted) {
        // remove row from the underlying data structure here
        fireTableRowsDeleted(rowIndex, rowIndex);
    }
    ...
}

请参阅AbstractTableModel API:

  • fireTableRowsInserted(int firstRow, int lastRow)
  • fireTableRowsDelete(int firstRow, int lastRow)

这样,列宽、行排序和筛选将保持不变。

 类似资料:
  • 问题内容: 我有一个JTable的第一行为空白。现在,当我通过单击列对表进行排序时,空白行位于底部。如果我在空白行中插入内容并进行排序,则该行将相应放置。即使已排序,如何跟踪其行索引。我需要访问该行,但是如果用户进行排序,那么我将失去行索引,因为它不再是第一行。 问题答案: 您所使用的假设Java 6中新增的东西,我认为你需要看看是什么方法和在类。你会做类似的事情 从模型中找出哪个可见行索引实际上

  • 我正在寻找一个持久的会话管理器,将会话保存在文件系统(如PHP)上,可以与DropWizard一起使用。我看到有一个<code>环境。getSessionHandler(),但我没有看到关于它的文档。 我可以写我自己的,但我希望有一个煮熟的饭。上面的会话句柄是我要找的吗?如何使用它?

  • 问题内容: 我的情况如下:我有一个数据表(少数字段,少于一百行),该数据表在程序中广泛使用。我还需要这些数据具有持久性,因此我将其另存为CSV并在启动时加载。我之所以选择不使用数据库,是因为每个选项(甚至是SQLite)对于我的卑微要求都是过高的(另外- 我希望能够以一种简单的方式离线编辑值,没有什么比记事本更简单的了)。 假设我的数据如下所示(在文件中用逗号分隔,没有标题,这只是一个示例): 笔

  • 问题内容: 我正在使用Nimbus L&F。我正在尝试通过使用以下代码来全局更改所有JTable的字体大小: 它正在工作,应用程序中所有JTable的行都使用新字体。我正在使用较大的字体大小,以使表在较大的分辨率下更具可读性。 但是问题是行高没有改变,导致字体被截断。我尝试了以下代码: 但这并没有改变显示表中的任何内容。 是否可以在不调用每个JTable实例的情况下全局更改行高? 问题答案: 基本

  • Navicat 为维护 Oracle 用户提供完整的解决方案。 在对象选项卡中选择用户。 右击已选择的用户。 选择“维护”,然后从弹出式菜单中选择一个维护选项。 选项 描述 密码过期 设置用户的密码为过期。 锁定帐号 锁定用户的帐号和禁用访问。 解除锁定帐号 解除锁定用户的帐号和启用访问。

  • Navicat 为维护 Oracle 用户提供完整的解决方案。 在对象选项卡中选择用户。 按住 Control 键并点按已选择的用户。 选择“维护”,然后从弹出式菜单中选择一个维护选项。 选项 描述 锁定用户 锁定用户的帐号和禁用访问。 解除锁定用户 解除锁定用户的帐号和启用访问。 过期用户 设置用户的密码为过期。