Java 同步两个JTable的视图

Java 同步两个JTable的视图,java,swing,jtable,jtableheader,jide,Java,Swing,Jtable,Jtableheader,Jide,我有两个JTables,一个在主视口,一个在页脚视口,使用JideScrollPane。 问题是,当自定义主JTable视图时,页脚JTable仍然是 同样,有什么方法可以同步他们的视图吗 谢谢 您可以应用:第一个JTable观察第二个JTable,反之亦然。然后将列表器添加到两个表中,以便在其中一个表被“定制”时,通知另一个表。基本上,“被通知”包含一个导致JTable更新的方法调用。 为此,您有两个选择: 使用“register”方法和 “通知”方法。在创建JTable时,将其注册到 观察者

我有两个
JTables
,一个在主视口,一个在页脚视口,使用
JideScrollPane
。 问题是,当自定义主
JTable
视图时,页脚
JTable
仍然是 同样,有什么方法可以同步他们的视图吗

谢谢

您可以应用:第一个JTable观察第二个JTable,反之亦然。然后将列表器添加到两个表中,以便在其中一个表被“定制”时,通知另一个表。基本上,“被通知”包含一个导致JTable更新的方法调用。 为此,您有两个选择:

  • 使用“register”方法和 “通知”方法。在创建JTable时,将其注册到 观察者然后,创建并关联到每个JTable的侦听器 调用观察者的“notify”方法,该方法通知所有其他观察者 变更登记表
  • 在包含并声明JTable的类中定义一种“回调方法”notify。此“notify”方法在listner中调用,并更新正确的JTable。您还可以创建两个方法:一个用于更新一个JTable,另一个用于更新另一个JTable
  • 编辑: 下面是一个演示,它将同步调整具有相似列的两个表的大小。这个想法是:

    • 为每个表的列模型创建自定义
      TableColumnModelListener
    • 调整大小后,同步列宽。发生这种情况时,您必须暂时禁用另一个侦听器
    • 要移动列,请在
      columnMoved(…)
      [作为练习离开]
    这显示双向同步:

    import java.awt.*;
    import java.util.*;
    import javax.swing.*;
    import javax.swing.event.*;
    import javax.swing.table.*;
    
    public class JTableResizeColumnsDemo implements Runnable
    {
      JTable table1, table2;
      TableColumnModelListener columnListener1, columnListener2;
      Map<JTable, TableColumnModelListener> map;
    
      public static void main(String[] args)
      {
        SwingUtilities.invokeLater(new JTableResizeColumnsDemo());
      }
    
      public void run()
      {
        Vector<String> names = new Vector<String>();
        names.add("One");
        names.add("Two");
        names.add("Three");
    
        table1 = new JTable(null, names);
        table2 = new JTable(null, names);
    
        columnListener1 = new ColumnChangeListener(table1, table2);
        columnListener2 = new ColumnChangeListener(table2, table1);
    
        table1.getColumnModel().addColumnModelListener(columnListener1);
        table2.getColumnModel().addColumnModelListener(columnListener2);
    
        map = new HashMap<JTable, TableColumnModelListener>();
        map.put(table1, columnListener1);
        map.put(table2, columnListener2);
    
        JPanel p = new JPanel(new GridLayout(2,1));
        p.add(new JScrollPane(table1));
        p.add(new JScrollPane(table2));
    
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(p);
        frame.setSize(300, 200);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
      }
    
      class ColumnChangeListener implements TableColumnModelListener
      {
        JTable sourceTable;
        JTable targetTable;
    
        public ColumnChangeListener(JTable source, JTable target)
        {
          this.sourceTable = source;
          this.targetTable = target;
        }
    
        public void columnAdded(TableColumnModelEvent e) {}
        public void columnSelectionChanged(ListSelectionEvent e) {}
        public void columnRemoved(TableColumnModelEvent e) {}
        public void columnMoved(TableColumnModelEvent e) {}
    
        public void columnMarginChanged(ChangeEvent e)
        {
          TableColumnModel sourceModel = sourceTable.getColumnModel();
          TableColumnModel targetModel = targetTable.getColumnModel();
          TableColumnModelListener listener = map.get(targetTable);
    
          targetModel.removeColumnModelListener(listener);
    
          for (int i = 0; i < sourceModel.getColumnCount(); i++)
          {
            targetModel.getColumn(i).setPreferredWidth(sourceModel.getColumn(i).getWidth());
          }
    
          targetModel.addColumnModelListener(listener);
        }
      }
    }
    
    import java.awt.*;
    导入java.util.*;
    导入javax.swing.*;
    导入javax.swing.event.*;
    导入javax.swing.table.*;
    公共类JTableResizeColumnsDemo实现Runnable
    {
    j表1、表2;
    TableColumnModelListener columnListener1、columnListener2;
    地图;
    公共静态void main(字符串[]args)
    {
    invokeLater(新的JTableResizeColumnsDemo());
    }
    公开募捐
    {
    向量名称=新向量();
    名称。添加(“一”);
    名称。添加(“两个”);
    名称。添加(“三”);
    表1=新的JTable(空,名称);
    表2=新的JTable(空,名称);
    columnListener1=新ColumnChangeListener(表1、表2);
    columnListener2=新ColumnChangeListener(表2,表1);
    表1.getColumnModel().addColumnModelListener(columnListener1);
    表2.getColumnModel().addColumnModelListener(columnListener2);
    map=新的HashMap();
    map.put(表1,columnListener1);
    map.put(表2,columnListener2);
    JPanel p=新JPanel(新网格布局(2,1));
    p、 添加(新的JScrollPane(表1));
    p、 添加(新的JScrollPane(表2));
    JFrame=新JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(p);
    框架。设置尺寸(300200);
    frame.setLocationRelativeTo(空);
    frame.setVisible(true);
    }
    类ColumnChangeListener实现TableColumnModelListener
    {
    JTable源表;
    JTable-targetable;
    公共ColumnChangeListener(JTable源、JTable目标)
    {
    this.sourceTable=source;
    this.targetTable=目标;
    }
    添加了公共空列(TableColumnModelEvent e){}
    public void columnSelectionChanged(ListSelectionEvent e){}
    已删除公共空列(TableColumnModelEvent e){}
    public void columnMoved(TableColumnModelEvent e){}
    公共无效列边际变更(变更事件e)
    {
    TableColumnModel sourceModel=sourceTable.getColumnModel();
    TableColumnModel targetModel=targetTable.getColumnModel();
    TableColumnModelListener=map.get(targetTable);
    removeColumnModelListener(listener);
    对于(int i=0;i
    通常这是通过为不同的ui组件使用相同的模型来实现的。遗憾的是,
    JTable
    中包含的内容在共享
    TableColumnModel
    时会导致问题

    但您可以使用此
    JTable

    class ShareableColumnModelTable extends JTable {
    
        /**
         * Fixes http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4816146 and
         * more...
         * 
         */
        @Override
        public void columnMarginChanged(ChangeEvent e) {
            if (isEditing()) {
                removeEditor();
            }
            TableColumn resizingColumn = null;
            if (tableHeader != null) {
                resizingColumn = tableHeader.getResizingColumn();
            }
            if (resizingColumn != null) {
                if (autoResizeMode == AUTO_RESIZE_OFF) {
                    resizingColumn.setPreferredWidth(resizingColumn.getWidth());
                } else { // this else block is missing in jdk1.4 as compared to
                            // 1.3
                    TableColumnModel columnModel = getColumnModel();
    
                    /**
                     * Temporarily disconnects this column listener to prevent
                     * stackoverflows if the column model is shared between
                     * multiple JTables.
                     */
                    columnModel.removeColumnModelListener(this);
                    try {
                        doLayout();
                    } finally {
                        columnModel.addColumnModelListener(this);
                    }
    
                    repaint();
                    return;
                }
            }
            resizeAndRepaint();
        }
    
    }
    
    使用上面显示的
    ShareableColumnModelTable
    ,您可以在多个表中更好地共享一列模型

    public static void main(String[] args) {
        JFrame frame = new JFrame("Column Sync");
    
        Container contentPane = frame.getContentPane();
        JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
        splitPane.setResizeWeight(0.5d);
        contentPane.add(splitPane);
    
        JTable table1 = new ShareableColumnModelTable();
        JTable table2 = new ShareableColumnModelTable();
    
        TableColumnModel tableColumnModel = createTableColumnModel();
    
        table1.setModel(createTableModel1());
        table2.setModel(createTableModel2());
    
        table1.setColumnModel(tableColumnModel);
        table2.setColumnModel(tableColumnModel);
    
        splitPane.setLeftComponent(new JScrollPane(table1));
        splitPane.setRightComponent(new JScrollPane(table2));
    
        showFrame(frame);
    }
    
    private static TableColumnModel createTableColumnModel() {
        TableColumnModel tableColumnModel = new DefaultTableColumnModel();
    
        TableColumn column1 = new TableColumn(0);
        column1.setHeaderValue("1. column");
        tableColumnModel.addColumn(column1);
    
        TableColumn column2 = new TableColumn(1);
        column2.setHeaderValue("2. column");
        tableColumnModel.addColumn(column2);
    
        return tableColumnModel;
    }
    
    private static TableModel createTableModel1() {
        DefaultTableModel tableModel = new DefaultTableModel();
        tableModel.setColumnCount(2);
        tableModel.addRow(new Object[] { "a", "b" });
        return tableModel;
    }
    
    private static TableModel createTableModel2() {
        DefaultTableModel tableModel = new DefaultTableModel();
        tableModel.setColumnCount(2);
        tableModel.addRow(new Object[] { "c", "d" });
        return tableModel;
    }
    
    private static void showFrame(JFrame frame) {
        frame.setSize(240, 400);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
    

    我确实考虑过这一点,遗憾的是,我不知道应该如何或确切地观察什么,因为JTable没有明显的视图面。另外,将它们设置为具有相同的模型只会定义它们的初始布局(数据+初始视图),而不是当前视图。好的,它确实有效。只需运行这个自包含的演示,您就会看到。很明显,您必须做一些不同的事情,但我不能说什么,因为您没有显示任何代码。为了更快地获得更好的帮助,请发布一个演示问题的帖子。我不希望数据被共享,我需要视图。主要是列的顺序和宽度,在运行时由用户修改,不修改基础数据。您想要两个具有相同结构(列标题等)但数据不同的表吗?如果是,那么您希望同步的是什么?滚动?列标题大小调整?还有什么?列标题的大小和顺序。主要是外表。页脚中的表应该是一个筛选行。@user3719495请参阅文章中的“我的编辑”。