Link to home
Start Free TrialLog in
Avatar of richard_fairall
richard_fairall

asked on

JTable Save and Restore viewed order of columns

Hi
I need to save the viewed order of the columns on a JTable,
(i.e. the user may have dragged columns around horizontally).
When the application restarts I need to restore the user's viewed column order.
I understand this order is maintained internally in JTable, and it would be better
if I did not change the actual initial order of the columns.
Any ideas?
Avatar of hoomanv
hoomanv
Flag of Canada image

this order is maintained internally in: TableColumnModel (horizontal order) and TableModel (vertical order)
maybe you should serilize these objects to a file and restore them
Avatar of richard_fairall

ASKER

Thanks but I dont want to use serialization here.
The application has an xml user-preferences file containing details of all window settings in the application.
I would like to save the info in xml  and restore the JTable column order from the same xml.
At least then I could programmatically avoid migration issues with incompatible serialized objects.
Rich
ASKER CERTIFIED SOLUTION
Avatar of hoomanv
hoomanv
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks, I know my way around Serializabe, Dom, xml etc
This request is about the possibility of getting some table column info order
and restoring the column view orders from it after the table is created.
I can see some usefu methods in JTable like convertColumnIndexToModel() and
convertColumnIndexToViewl()  but no way of programmatically restoring the orders.
I need to do this programmatically, without using serialization or XMLEncoder etc.
I dont think it's possible, do you?
Rich
Thanks Hoomany
I crossed over your input with my last entry.
That sounds like it will do the job.
> but no way of programmatically restoring the orders
see my last comment to get the columns orders
to rearrange columns to be in this order you should remove all columns from TableColumnModel and then try to add them in the specified order.

for example if they are in order: 2, 1, 0
you have to add column 2 first then column 1 and at last column 0
What about using getModelIndex() to restore?

Sorry I meant setModelIndex()
Sorry not help you.
it will change the modelindex of column but it wont move the column at the view level, so the best way I think is try to add columns from scratch
If I add columns (in any order) from scratch then my getValueAt() method will need to be mapped too?
yes I think
setModelIndex() could be helpful to map the view model to internal model
Thanks I have just had a look at the javadoc

setModelIndex()
Sets the model index for this column. The model index is the index of the column in the model that will be displayed by this TableColumn.
As the TableColumn is moved around in the view the model index remains constant.

Ok, so, a scenario:
1. I create a new Table with columns:  Tom, Dick, Harry.
2. User shuffles these around to: Dick, Tom, Harry.
3. Save view order info: 0,1,2  is  1,0,2  somehow.
4. Restart and build table columns as Dick, Tom, Harry.
5. Call setColumnIndex() for each column to fix original model index so getValueAt() can remain fixed.

or do I need another coffee?
Doesn't work as suggested, I need to focus on this a bit more.
In the table model, I think the solution will be:
1. Hold a list of column names that correspond to the order of the columns in getValueAt().
2. When constructing the model, take a list of column header names in the shuffled order.
3. Build the model using this shuffled list.
4. Create a lookup table to remap the columnIndex for getValueAt().
5. Do   getValueAt(row,  getColumnOrder(lookupTable);
I've created this sample code to demonstrate how you can achieve this
in line --> int[] newOrd = {2,4,0,3,1};
you can provide any order, and by pressing reorder button, columns will be rearranged to that order


/*******************************/
import java.util.*;
import javax.swing.table.*;

public class NewJFrame extends javax.swing.JFrame {
      
      public NewJFrame() {
            initComponents();
      }
      
    private void initComponents() {
        jScrollPane1 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();
        jPanel1 = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();
        jButton2 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        jTable1.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {"0", "1", "2", "3", "4"},
                {"0", "1", "2", "3", "4"},
                {"0", "1", "2", "3", "4"},
                {"0", "1", "2", "3", "4"}
            },
            new String [] {
                "0", "1", "2", "3", "4"
            }
        ));
        jScrollPane1.setViewportView(jTable1);

        getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);

        jButton1.setText("order");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        jPanel1.add(jButton1);

        jButton2.setText("reorder");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });

        jPanel1.add(jButton2);

        getContentPane().add(jPanel1, java.awt.BorderLayout.SOUTH);

        pack();
    }

      private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                        
            int numCol = jTable1.getColumnCount();
            int[] newOrd = {2,4,0,3,1};
            int[] curOrd = new int[numCol];
            
            Enumeration<TableColumn> e = jTable1.getColumnModel().getColumns();
            for(int i = 0; e.hasMoreElements(); i++)
                  curOrd[i] = e.nextElement().getModelIndex();
            
            for(int i = 0, p; i < numCol; i++) {
                  for(p = i; curOrd[p] != newOrd[i]; p++)
                        ;
                  
                  for(int j = p; j > i; j--)
                        curOrd[j] = curOrd[j-1];
                  curOrd[i] = curOrd[p];
                  
                  jTable1.getColumnModel().moveColumn(p, i);
            }
      }                                        

      private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                        
            Enumeration<TableColumn> e = jTable1.getColumnModel().getColumns();
            while(e.hasMoreElements()) {
                  System.out.print(e.nextElement().getModelIndex() + " ");
            }
            System.out.println();
      }                                        
      
      public static void main(String args[]) {
            java.awt.EventQueue.invokeLater(new Runnable() {
                  public void run() {
                        new NewJFrame().setVisible(true);
                  }
            });
      }
      
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable jTable1;
      
}
sample version 2

/************************/

import java.util.*;
import javax.swing.table.*;

public class NewJFrame extends javax.swing.JFrame {
      
      public NewJFrame() {
            initComponents();
      }
      
    private void initComponents() {
        jScrollPane1 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();
        jPanel1 = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();
        jButton2 = new javax.swing.JButton();
        jTextField1 = new javax.swing.JTextField();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        jTable1.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {"0", "1", "2", "3", "4"},
                {"0", "1", "2", "3", "4"},
                {"0", "1", "2", "3", "4"},
                {"0", "1", "2", "3", "4"}
            },
            new String [] {
                "0", "1", "2", "3", "4"
            }
        ));
        jScrollPane1.setViewportView(jTable1);

        getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);

        jButton1.setText("order");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        jPanel1.add(jButton1);

        jButton2.setText("reorder");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });

        jPanel1.add(jButton2);

        jTextField1.setText("2,4,0,3,1");
        jPanel1.add(jTextField1);

        getContentPane().add(jPanel1, java.awt.BorderLayout.SOUTH);

        pack();
    }

      private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                        
            int numCol = jTable1.getColumnCount();
            int[] newOrd = new int[numCol];
            int[] curOrd = new int[numCol];
            
            String[] strOrd = jTextField1.getText().split(",");
            for(int i=0; i < strOrd.length; i++)
                  newOrd[i] = Integer.parseInt(strOrd[i]);
            
            Enumeration<TableColumn> e = jTable1.getColumnModel().getColumns();
            for(int i = 0; e.hasMoreElements(); i++)
                  curOrd[i] = e.nextElement().getModelIndex();
            
            for(int i = 0, p; i < numCol; i++) {
                  for(p = i; curOrd[p] != newOrd[i]; p++)
                        ;
                  
                  int q = curOrd[p];
                  for(int j = p; j > i; j--)
                        curOrd[j] = curOrd[j-1];
                  curOrd[i] = q;
                  
                  jTable1.getColumnModel().moveColumn(p, i);
            }
      }                                        

      private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                        
            Enumeration<TableColumn> e = jTable1.getColumnModel().getColumns();
            while(e.hasMoreElements()) {
                  System.out.print(e.nextElement().getModelIndex() + " ");
            }
            System.out.println();
      }                                        
      
      public static void main(String args[]) {
            java.awt.EventQueue.invokeLater(new Runnable() {
                  public void run() {
                        new NewJFrame().setVisible(true);
                  }
            });
      }
      
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable jTable1;
    private javax.swing.JTextField jTextField1;
      
}
Thanks a bundle mate, I'll give it a whirl.
Rich