拖动后如何将JTable列排序到原始位置

问题描述

我有一个JTable,我想让用户可以按自己的意愿对列进行定位,以获取信息的自定义视图。但是同时,当发生特定事件时,我需要一个函数(或算法)来将这些列设置为其原始位置。

我知道,当您要访问单元格中的数据时,无论用户将其设置在什么位置,列的索引都将保持不变。

例如:一个具有3列的JTable,例如column1,column2,column3。如果用户拖动它们以将其显示为column2,column3,column1,则column1仍将具有0索引。因此,必须有一种方法可以轻松地将其重新排序为原始位置。我知道要访问列的重新排序,您需要获取标题

jtableheader header = table.getTableHeader();
header.setReorderingallowed(true);

因此,从那里我看了jtableheader类的文档,但是我没有找到任何有用的东西,也没有通过搜索特定的解决方案。我希望我已经正确解释了这个问题。这是我的代码的类似示例。

DefaultTableModel model = new DefaultTableModel();
table = new JTable(model);
model.addColumn(column1);
model.addColumn(column2);
model.addColumn(column3);
jtableheader header = table.getTableHeader();
header.setReorderingallowed(true);


JButton button = new JButton("Reorder");
button.addActionListener(new ActionListener){
    @Override
    public void actionPerformed(ActionEvent e) {
     //the code that orders the columns to its original position         
   }
};

我也知道认情况下,列的重新排序设置为true,但是我添加了它是为了使之更清楚,并知道我还能从中添加或做些什么。

编辑1 第一种解决方案,在名为private static int[] ColumnsWidth自定义类中使用HelperArrays数组,并根据需要使用列宽,其中getter方法返回用于每列宽度的int,设置为参数数组的索引。我们可以从JTable对象中重置DefaultTableModel,但是还需要重置列的宽度,以便成功地将列重新排序到其原始位置

  private static int[] columnsWidhth = {widht1,widhth2,width3};

  public static int getColumnsWidth(int index){
  returns ColumnsWidth[index];
  }

  @Override
  public void actionPerformed(ActionEvent e) {
      table.setModel(new DefaultTableModel());
      table.setModel(model);
      DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
      centerRenderer.setHorizontalAlignment(JLabel.CENTER);
      for (int i = 0; i < table.getColumnCount(); i++) {
          table.getColumnModel().getColumn(i).setMinWidth(HelperArrays.getColumnsWidth(i));
          table.getColumnModel().getColumn(i).setMaxWidth(HelperArrays.getColumnsWidth(i));
          table.getColumnModel().getColumn(i).setPreferredWidth(HelperArrays.getColumnsWidth(i));      
      }
  }

编辑2 第二个也是最后一个解决方案,直接使用moveColumn()对象中的TableColumnModel函数对列进行重新排序,并使用循环按其原始索引还原它们。

@Override
public void actionPerformed(ActionEvent e) {
    TableModel model = table.getModel();
    TableColumnModel tcm = table.getColumnModel();
    for (int i = 0; i < model.getColumnCount() - 1; i++) {
            int location = tcm.getColumnIndex(model.getColumnName(i));
            tcm.moveColumn(location,i);
   }

}

解决方法

所以从那里我看了JTableHeader的文档

TableColumn中包含有关TableColumnModel的显示方式的信息。

您可以只使用moveColumn(...)方法来恢复列顺序。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;

public class TableColumnRestore2 extends JFrame
{
    public TableColumnRestore2()
    {
        final JTable table = new JTable(5,8);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JScrollPane scrollPane= new JScrollPane( table );
        getContentPane().add(scrollPane);

        JButton restore = new JButton("Restore Columns");
        getContentPane().add(restore,BorderLayout.SOUTH);
        restore.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                TableModel model = table.getModel();
                TableColumnModel tcm = table.getColumnModel();

                for (int i = 0; i < model.getColumnCount() - 1; i++)
                {
                    int location = tcm.getColumnIndex( model.getColumnName(i) );
                    tcm.moveColumn(location,i);
                }
            }
        });
    }

    public static void main(String[] args)
    {
        TableColumnRestore2 frame = new TableColumnRestore2();
        frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }
}
,

我不知道是否有更好的解决方案,但这似乎可行:

TableModel model = table.getModel();
table.setModel(new DefaultTableModel());
table.setModel(model);

完整示例:

public class TableColumnOrderTest {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            DefaultTableModel dm = new DefaultTableModel();
            dm.addColumn("Column 1");
            dm.addColumn("Column 2");
            dm.addColumn("Column 3");
            dm.addColumn("Column 4");

            Object[][] data = { 
                    { "1","Something","hello","World" },{ "102","Something Else" },{ "55","dfsdf","fsdafas" },{ "66","Something" },{ "1000",{ "1524",{ "5801",{ "-55",};

            for (Object[] row : data) {
                dm.addRow(row);
            }
            JTable table = new JTable(dm);

            JPanel panel = new JPanel(new BorderLayout());
            panel.add(new JScrollPane(table));

            JButton button = new JButton("button");
            button.addActionListener(e -> {
                table.setModel(new DefaultTableModel());
                table.setModel(dm);
            });

            panel.add(button,BorderLayout.PAGE_END);
            JOptionPane.showMessageDialog(null,panel);
        });
    }
}

预览:

image

编辑

最近我问了how to restore column widths。删除并重新添加模型会使表的渲染器变形。如果您使用自定义TableCellRenderers,并且想要在重新设置模型后保留它们,则可以使用以下内容:

private static void restoreColumnOrdering(JTable table) {
    TableModel model = table.getModel();
    Map<Object,TableCellRenderer> renderers = new HashMap<>();
    Map<Object,Integer> widths = new HashMap<>();

    for (int i = 0; i < table.getColumnCount(); i++) {
        TableColumn column = table.getColumnModel().getColumn(i);
        TableCellRenderer cellRenderer = column.getCellRenderer();
        renderers.put(column.getIdentifier(),cellRenderer);
        widths.put(column.getIdentifier(),column.getPreferredWidth());
    }

    table.setModel(new DefaultTableModel());
    table.setModel(model);

    // Reset renderers
    for (int i = 0; i < table.getColumnCount(); i++) {
        TableColumn column = table.getColumnModel().getColumn(i);
        TableCellRenderer cellRenderer = renderers.get(column.getIdentifier());
        column.setCellRenderer(cellRenderer);
        column.setPreferredWidth(widths.get(column.getIdentifier()));
    }
}