How do multiple JTable headers synchronize column widths, sorting, etc.?

I have an interface that has several small JTables stacked on top of each other. I would like their column sizes, sorting, filtering, etc. Remained in sync. Is there an easy way to do this?

For column widths, I tried using the generic TableHeaderModel method, but this seemed to create unforeseen problems, such as being able to resize using the last table added. I could live by simply having the width of the columns, staying in sync, being able to resize using any of the tables, if anyone has a solution.

I posted the below code example. At startup, you will notice that you cannot resize the first or second table headers, but the third one resizes them. I want the behavior of a third table, but from any table header.

Thank.

package javaapplication5;

public class NewJFrame extends javax.swing.JFrame {

  private javax.swing.JScrollPane jScrollPane1;
  private javax.swing.JScrollPane jScrollPane2;
  private javax.swing.JScrollPane jScrollPane3;
  private javax.swing.JTable jTable1;
  private javax.swing.JTable jTable2;
  private javax.swing.JTable jTable3;

  public NewJFrame() {
      initComponents();

      jTable2.setColumnModel(jTable1.getColumnModel());
      jTable3.setColumnModel(jTable1.getColumnModel());        
  }

  private void initComponents() {

      jScrollPane1 = new javax.swing.JScrollPane();
      jTable1 = new javax.swing.JTable();
      jScrollPane2 = new javax.swing.JScrollPane();
      jTable2 = new javax.swing.JTable();
      jScrollPane3 = new javax.swing.JScrollPane();
      jTable3 = new javax.swing.JTable();

      setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
      getContentPane().setLayout(new javax.swing.BoxLayout(getContentPane(),             
          javax.swing.BoxLayout.Y_AXIS));

      jTable1.setModel(new javax.swing.table.DefaultTableModel(
          new Object [][] {
            {"a", "b", "c", "d"},
            {"e", "f", "g", "h"},
            {"i", "j", "k", "l"},
            {"m", "n", "o", "p"}
          },
          new String [] {
            "Title 1", "Title 2", "Title 3", "Title 4"
          }
      ));
      jScrollPane1.setViewportView(jTable1);

      getContentPane().add(jScrollPane1);

      jTable2.setModel(new javax.swing.table.DefaultTableModel(
          new Object [][] {
            {"q", "r", "s", "t"},
            {"u", "v", "w", "x"},
            {"y", "z", "1", "2"},
            {"3", "4", "5", "6"}
          },
          new String [] {
            "Title 1", "Title 2", "Title 3", "Title 4"
          }
      ));
      jScrollPane2.setViewportView(jTable2);

      getContentPane().add(jScrollPane2);

      jTable3.setModel(new javax.swing.table.DefaultTableModel(
        new Object [][] {
            {"7", "8", "9", "10"},
            {"11", "12", "13", "14"},
            {"15", "16", "17", "18"},
            {"19", "20", "21", "22"}
        },
        new String [] {
            "Title 1", "Title 2", "Title 3", "Title 4"
        }
      ));
      jScrollPane3.setViewportView(jTable3);

      getContentPane().add(jScrollPane3);

      pack();
  }

  public static void main(String args[]) {
      java.awt.EventQueue.invokeLater(new Runnable() {
          public void run() {
              new NewJFrame().setVisible(true);
          }
      });
  }
}
+3
source share
2 answers

While waiting for an answer, I came across a fix for my problem. This seems to be a known bug. I used the solution posted here, with the comments modified below.

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4816146

+4
source
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.table.*;

class Application extends JFrame
{
    public Application()
    {
        this.setBounds(100,100,500,200);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        String data[][] = {{"a1","b1","c1"},{"a2","b2","c2"},{"a3","b3","c3"}};
        String columnNames[] = {"a","b","c"};

        JTable jtable = new JTable(new DefaultTableModel(data,columnNames));

        JScrollPane jscrollPane = new JScrollPane(jtable,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        jscrollPane.setBorder(new CompoundBorder(new MatteBorder(0,0,1,0,Color.gray),new EmptyBorder(0,0,0,0)));

        this.add(jscrollPane,BorderLayout.CENTER);


        JTable jtable_footer = new JTable(new DefaultTableModel(3,columnNames.length),jtable.getColumnModel());

        SyncListener syncListener = new SyncListener(jtable,jtable_footer);

        this.add(jtable_footer,BorderLayout.SOUTH);
    }

    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                Application application = new Application();

                application.setVisible(true);
            }
        });
    }
}

class SyncListener implements TableColumnModelListener
{
    JTable jtable_data;
    JTable jtable_footer;

    public SyncListener(JTable main, JTable footer)
    {
        jtable_data = main;
        jtable_footer = footer;

        DefaultTableColumnModel dtcm = (DefaultTableColumnModel)jtable_data.getColumnModel();

        // this is the listener causing resize problems
        dtcm.removeColumnModelListener(dtcm.getColumnModelListeners()[1]); 
        dtcm.addColumnModelListener(this);
    }

    public void columnMarginChanged(ChangeEvent changeEvent)
    {
        for (int column = 0; column < jtable_data.getColumnCount(); column++)
        {
            jtable_footer.getColumnModel().getColumn(column).setWidth(jtable_data.getColumnModel().getColumn(column).getWidth());
        }

        jtable_footer.repaint();
    }

    public void columnAdded(TableColumnModelEvent e){}
    public void columnMoved(TableColumnModelEvent e){}
    public void columnRemoved(TableColumnModelEvent e){}
    public void columnSelectionChanged(ListSelectionEvent e){}
}
+1
source

Source: https://habr.com/ru/post/1753917/


All Articles