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?
richard_fairallAsked:
Who is Participating?
 
hoomanvConnect With a Mentor Commented:
with this code you can get the order of columns

Enumeration<TableColumn> e = jTable.getColumnModel().getColumns();
while(e.hasMoreElements()) {
      e.nextElement().getModelIndex();
}

you can then use these info later to restore the privious view
0
 
hoomanvCommented:
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
0
Cloud Class® Course: MCSA MCSE Windows Server 2012

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

 
richard_fairallAuthor Commented:
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
0
 
Giant2Commented:
0
 
richard_fairallAuthor Commented:
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
0
 
richard_fairallAuthor Commented:
Thanks Hoomany
I crossed over your input with my last entry.
That sounds like it will do the job.
0
 
hoomanvCommented:
> 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
0
 
richard_fairallAuthor Commented:
What about using getModelIndex() to restore?

0
 
richard_fairallAuthor Commented:
Sorry I meant setModelIndex()
0
 
Giant2Commented:
Sorry not help you.
0
 
hoomanvCommented:
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
0
 
richard_fairallAuthor Commented:
If I add columns (in any order) from scratch then my getValueAt() method will need to be mapped too?
0
 
hoomanvCommented:
yes I think
setModelIndex() could be helpful to map the view model to internal model
0
 
richard_fairallAuthor Commented:
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?
0
 
richard_fairallAuthor Commented:
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);
0
 
hoomanvCommented:
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;
      
}
0
 
hoomanvCommented:
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;
      
}
0
 
richard_fairallAuthor Commented:
Thanks a bundle mate, I'll give it a whirl.
Rich
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.