3

JTables在主视口中有两个,一个在页脚视口中,使用JideScrollPane. 问题是当 mainJTable的视图被自定义时,页脚JTable保持不变,有没有办法同步他们的视图?

谢谢。

不同步

4

3 回答 3

4

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

  • TableColumnModelListener为每个表的列模型创建自定义。
  • 调整大小后,同步列宽。在发生这种情况时,您必须暂时禁用另一个侦听器。
  • 对于列的移动,在columnMoved(...)[left as an practice]中实现该逻辑

这显示了双向同步:

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);
    }
  }
}
于 2014-09-17T17:50:47.383 回答
1

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

  1. 您使用“注册”方法和“通知”方法定义了一个类 Observer。创建 JTable 时,将其注册到 Observer。然后,您创建并关联到每个 JTable 的侦听器调用观察者的“通知”方法,该方法将更改通知所有其他已注册的 JTable
  2. 您在包含和声明 JTable 的类中定义了一种“回调方法”通知。这个“通知”方法在列表器中被调用并更新正确的 JTable。您还可以创建两种方法:一种用于更新一个 JTable,另一种用于更新另一个 JTable
于 2014-09-17T17:33:16.833 回答
0

通常这是通过对不同的 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);
}

在此处输入图像描述

于 2017-06-28T11:15:38.123 回答