如何在拖动后将 JTable 列排序为原始位置。

huangapple go评论82阅读模式
英文:

How to order JTable columns to original position after being draged

问题

我有一个 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) {
        // 对列进行重新排序到原始位置的代码
    }
};

我也知道默认情况下列的重新排序设置为 true,但我添加了这句话以使其更清楚,并了解还可以添加或从中做些什么。

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

private static int[] columnsWidth = {width1, width2, width3};

public static int getColumnsWidth(int index) {
    return 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
第二种也是最终的解决方案,直接使用 TableColumnModel 对象的 moveColumn() 函数重新排序列,使用循环按原始索引还原它们。

@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);
    }
}
英文:

I have a JTable and I want to give the users the possibility to position the columns as they want for a custom view of the information. But at the same time I'm needing a function (or an algorithm) to set these columns to it's original position when an specific event occurs.

I know that when you want to access to the data in a cell, the index of the column will still remain the same no matter on what position the user have set it.

For example: a JTable with 3 columns, let's say column1, column2, column3. If the user drags them to be displayed as column2, column3, column1, then column1 will still have the 0 index. So there must be a way to easily reordering them back to it's original position. I know that to access to the reordering of a column you need to get the header.

JTableHeader header = table.getTableHeader();
header.setReorderingAllowed(true);

So from there I looked at the documentation of JTableHeader class but I didn't find anything useful, neither by searching an specific solution. I hope I have explained properly this problem. This is a similar example of my code.

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(&quot;Reorder&quot;);
button.addActionListener(new ActionListener){
    @Override
    public void actionPerformed(ActionEvent e) {
     //the code that orders the columns to its original position         
   }
};

Also I know that by default the reordering of the columns is set as true, but I added it to make it clear and to know what else I could add or do from there.

EDIT 1
first solution, using a private static int[] ColumnsWidth Array in a custom class called HelperArrays with the width of the columns as I need, in which the getter method returns the int used for the width of the each column, setting as parameter the index of the Array. We can reset the DefaultTableModel from the JTable Object but will be needed to also reset the widths of the columns in order to succesfully reorder columns to their original position

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

EDIT 2
Second and final solution, reordering the columns directly with the moveColumn() function from the TableColumnModel Object, using a loop to restore them by their original index.

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

}

答案1

得分: 2

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

关于如何显示 TableColumn 的信息包含在 TableColumnModel 中

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

```java
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("还原列顺序");
        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);
    }
}
英文:

> So from there I looked at the documentation of JTableHeader

The information about how the TableColumns are display is contained in the TableColumnModel.

You can just use the moveColumn(...) method to restore the column order.

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(&quot;Restore Columns&quot;);
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 &lt; 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);
}
}

答案2

得分: -1

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

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", "Something", "dfsdf", "fsdafas" }, { "66", "Something" },
                { "1000", "Something" }, { "1524", "Something" },
                { "5801", "Something" }, { "-55", "Something" },
            };

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

预览:

如何在拖动后将 JTable 列排序为原始位置。

编辑

最近我询问了如何恢复列宽度。删除并重新添加模型将清除表格的渲染器。如果您使用自定义的 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);

    // 重置渲染器
    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()));
    }
}
英文:

I am not aware if there is a better solution, but this seems to work:

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

A full example:

public class TableColumnOrderTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -&gt; {
DefaultTableModel dm = new DefaultTableModel();
dm.addColumn(&quot;Column 1&quot;);
dm.addColumn(&quot;Column 2&quot;);
dm.addColumn(&quot;Column 3&quot;);
dm.addColumn(&quot;Column 4&quot;);
Object[][] data = { 
{ &quot;1&quot;, &quot;Something&quot;,&quot;hello&quot;,&quot;World&quot; }, { &quot;102&quot;, &quot;Something Else&quot; }, 
{ &quot;55&quot;, &quot;Something&quot;,&quot;dfsdf&quot;,&quot;fsdafas&quot; }, { &quot;66&quot;, &quot;Something&quot; },
{ &quot;1000&quot;, &quot;Something&quot; }, { &quot;1524&quot;, &quot;Something&quot; }, 
{ &quot;5801&quot;, &quot;Something&quot; }, { &quot;-55&quot;, &quot;Something&quot; },};
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(&quot;button&quot;);
button.addActionListener(e -&gt; {
table.setModel(new DefaultTableModel());
table.setModel(dm);
});
panel.add(button, BorderLayout.PAGE_END);
JOptionPane.showMessageDialog(null, panel);
});
}
}

Preview:

如何在拖动后将 JTable 列排序为原始位置。

EDIT

Recently I asked how to restore column widths. Removing and re-adding the model will whack the renderers of the table. You can use something like the following in case you use custom TableCellRenderers and you want to preserve them after re-setting the model:

private static void restoreColumnOrdering(JTable table) {
TableModel model = table.getModel();
Map&lt;Object, TableCellRenderer&gt; renderers = new HashMap&lt;&gt;();
Map&lt;Object, Integer&gt; widths = new HashMap&lt;&gt;();
for (int i = 0; i &lt; 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 &lt; table.getColumnCount(); i++) {
TableColumn column = table.getColumnModel().getColumn(i);
TableCellRenderer cellRenderer = renderers.get(column.getIdentifier());
column.setCellRenderer(cellRenderer);
column.setPreferredWidth(widths.get(column.getIdentifier()));
}
}

huangapple
  • 本文由 发表于 2020年8月15日 05:09:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/63420045.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定