同步两个JTable的视图

时间:2014-09-17 17:09:13

标签: java swing jtable jtableheader jide

我在主视口中有两个JTables,在页脚视口中有一个JideScrollPane。 问题是当自定义主JTable视图时,页脚JTable仍然是 同样,有没有办法同步他们的观点?

感谢。

unsynch

3 个答案:

答案 0 :(得分:4)

修改 这是一个演示,它将同步调整两个具有相似列的表的大小。这个想法是:

  • 为每个表格的列模型创建自定义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);
    }
  }
}

答案 1 :(得分:1)

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

  1. 使用“register”方法和a定义一个Observer类 “通知”方法。创建JTable时,请将其注册到 观察员。然后,您创建并与每个JTable关联的侦听器 调用观察者的“notify”方法,通知所有其他方法 注册的JTables的变化
  2. 您在包含并声明JTable的类中定义了一种“回调方法”notify。在listner中调用此“notify”方法并更新正确的JTable。您还可以创建两个方法:一个用于更新一个JTable,另一个用于另一个JTable

答案 2 :(得分:0)

通常这是通过对不同的ui组件使用相同的模型来完成的。遗憾的是JTable包含a bug,在共享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);
}

enter image description here