在双JTable中调整列的大小

我正在创建一个包含2个JTables的自定义组件,其中一个作为主数据网格,另一个作为总是可见的汇总栏,而且我已经提出了这个解决方案,但是调整列的大小并不像应该那样工作,任何想法我做了什么错误?

import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; public class FixedRow2Tables extends JFrame { private static final long serialVersionUID = 4676303089799270571L; Object[][] data; Object[] column; JTable fixedTable, table; public FixedRow2Tables() { super("Fixed Row Example"); Object[][] mainData = new Object[][] { { "a", "", "", "", "", "" }, { "", "b", "", "", "", "" }, { "", "", "c", "", "", "" }, { "", "", "", "d", "", "" }, { "", "", "", "", "e", "" }, { "", "", "", "", "", "f" } }; Object[][] summaryData = { { "fixed1", "", "", "", "", "" }, { "fixed2", "", "", "", "", "" } }; column = new Object[] { "A", "B", "C", "D", "E", "F" }; table = new JTable(mainData, column); table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); fixedTable = new JTable(summaryData, column); fixedTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); fixedTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); fixedTable.setTableHeader(null); fixedTable.setColumnModel(table.getColumnModel()); JScrollPane scroll = new JScrollPane(table); scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); scroll.setPreferredSize(new Dimension(400, 100)); getContentPane().add(scroll, BorderLayout.CENTER); getContentPane().add(fixedTable, BorderLayout.SOUTH); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { FixedRow2Tables frame = new FixedRow2Tables(); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); frame.pack(); frame.setVisible(true); } }); } } 

 fixedTable.setColumnModel(table.getColumnModel()); 

问题在于这条线。 如果您将其注释掉,表格表现正常。 如果这打破了你的代码(因为我不知道你想要做什么)只是评论。

但是,当你在你的评论中添加,你想同步两个表。 我发现一个论坛线程,涵盖了这个问题:

http://forums.sun.com/thread.jspa?threadID=713021

玩的开心!

PS:以防万一论坛线程消失(只是复制文本):

首先勾上桌子。 不得不分享ColumnModel否则它没有工作。 这两个面板都有一个JTable字段,并将set和ColumnModel方法委托给

 JTable. infoPanel.setColumnModel(overviewPanel.getColumnModel()); overviewPanel.getColumnModel().addColumnModelListener(infoPanel); infoPanel.getColumnModel().addColumnModelListener(overviewPanel); 

然后处理ChangeEvent:

 public void columnMarginChanged(ChangeEvent event) { final TableColumnModel eventModel = (DefaultTableColumnModel)event.getSource(); final TableColumnModel thisModel = getTable().getColumnModel(); final int columnCount = eventModel.getColumnCount(); for (int i = 0; i < columnCount; i++) { thisModel.getColumn(i).setWidth(eventModel.getColumn(i).getWidth()); } repaint(); } 

这段代码为我修好了。

请注意,columnModel不在表格之间重复使用。 请参阅代码中的注释。

 package snippet; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ListSelectionEvent; import javax.swing.event.TableColumnModelEvent; import javax.swing.event.TableColumnModelListener; import javax.swing.table.TableColumnModel; public class FixedRow2Tables extends JFrame { private static final long serialVersionUID = 4676303089799270571L; Object[][] data; Object[] column; JTable footerTable, table; public FixedRow2Tables() { super("Fixed Row Example"); Object[][] mainData = new Object[][] { { "a", "", "", "", "", "" }, { "", "b", "", "", "", "" }, { "", "", "c", "", "", "" }, { "", "", "", "d", "", "" }, { "", "", "", "", "e", "" }, { "", "", "", "", "", "f" } }; Object[][] summaryData = { { "fixed1", "", "", "", "", "" }, { "fixed2", "", "", "", "", "" } }; column = new Object[] { "A", "B", "C", "D", "E", "F" }; table = new JTable(mainData, column); table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); footerTable = new JTable(summaryData, column); footerTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); footerTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); footerTable.setTableHeader(null); // footerTable.setColumnModel(table.getColumnModel()); table.getColumnModel().addColumnModelListener( new TableColumnModelListener() { @Override public void columnSelectionChanged(ListSelectionEvent e) { } @Override public void columnRemoved(TableColumnModelEvent e) { } @Override public void columnMoved(TableColumnModelEvent e) { } @Override public void columnMarginChanged(ChangeEvent e) { final TableColumnModel tableColumnModel = table .getColumnModel(); TableColumnModel footerColumnModel = footerTable .getColumnModel(); for (int i = 0; i < tableColumnModel.getColumnCount(); i++) { int w = tableColumnModel.getColumn(i).getWidth(); footerColumnModel.getColumn(i).setMinWidth(w); footerColumnModel.getColumn(i).setMaxWidth(w); // footerColumnModel.getColumn(i).setPreferredWidth(w); } footerTable.doLayout(); footerTable.repaint(); repaint(); } @Override public void columnAdded(TableColumnModelEvent e) { } }); JScrollPane scroll = new JScrollPane(table); scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); scroll.setPreferredSize(new Dimension(400, 100)); getContentPane().add(scroll, BorderLayout.CENTER); getContentPane().add(footerTable, BorderLayout.SOUTH); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { FixedRow2Tables frame = new FixedRow2Tables(); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); frame.pack(); frame.setVisible(true); } }); } } 
 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(); 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){} } 

我对这个问题的解决方案(代码在Kotlin):

 class TableHack(model: TableModel) : JXTable(model) { override fun columnMarginChanged(e: ChangeEvent?) { repaint(); return; } } 

使用此表作为“摘要” – 表,并从主表中设置ColumnModel

问题的原因似乎是resizeAndRepaint() ,它是从表内的默认实现中调用的。 如果你用一个简单的repaint()替换它,它就像一个魅力。

在上面的例子中,我添加了一些水平滚动条和列顺序的东西:

 package test; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.AdjustmentEvent; import java.awt.event.AdjustmentListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Enumeration; import javax.swing.JFrame; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ListSelectionEvent; import javax.swing.event.TableColumnModelEvent; import javax.swing.event.TableColumnModelListener; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; public class FixedRow2Tables extends JFrame { class FixedFooterTable extends JTable { private TableColumnModelListener tableColumnModelListener; private JTable bindedTable; FixedFooterTable(Object[][] data, String[] columnNames) { super(data, columnNames); setAutoResizeMode(JTable.AUTO_RESIZE_OFF); setSelectionMode(ListSelectionModel.SINGLE_SELECTION); setCellSelectionEnabled(true); } public void bindTableModels(final JTable table) { this.bindedTable = table; if (tableColumnModelListener == null) tableColumnModelListener = new TableColumnModelListener() { @Override public void columnSelectionChanged(ListSelectionEvent e) { } @Override public void columnRemoved(TableColumnModelEvent e) { if (e.getFromIndex() < getColumnCount()) { TableColumn c = getColumnModel().getColumn(e.getFromIndex()); getColumnModel().removeColumn(c); } } @Override public void columnMoved(TableColumnModelEvent e) { if (e.getFromIndex() < getColumnCount() && e.getToIndex() < getColumnCount()) { TableColumn c = getColumnModel().getColumn(e.getFromIndex()); getColumnModel().moveColumn(e.getFromIndex(), e.getToIndex()); } } @Override public void columnMarginChanged(ChangeEvent e) { bindColumnWidths(table.getColumnModel()); } @Override public void columnAdded(TableColumnModelEvent e) { } }; table.getColumnModel().addColumnModelListener(tableColumnModelListener); } private void bindColumnWidths(final TableColumnModel columnModel) { TableColumnModel fixedColumnModel = getColumnModel(); Enumeration<TableColumn> enumerator = columnModel.getColumns(); while (enumerator.hasMoreElements()) { TableColumn c = enumerator.nextElement(); if (c.getModelIndex() >= fixedColumnModel.getColumnCount()) break; TableColumn destColumn = fixedColumnModel.getColumn(c.getModelIndex()); System.out.println("columnMarginChanged c" + c.getModelIndex() + " : " + c.getWidth() + " - " + destColumn.getWidth() + " : " + (destColumn.getWidth() - c.getWidth())); destColumn.setPreferredWidth(c.getWidth()); System.out.println("columnMarginChanged c" + c.getModelIndex() + " : " + c.getWidth() + " - " + destColumn.getWidth()); } revalidate(); } @Override public boolean isCellEditable(int row, int column) { return false; } public void bindViews(final JScrollPane scrollPane, final JScrollPane fixedScrollPane) { final JScrollBar fixedHorScrollBar = fixedScrollPane.getHorizontalScrollBar(); final JScrollBar horScrollBar = scrollPane.getHorizontalScrollBar(); final JScrollBar verScrollBar = scrollPane.getVerticalScrollBar(); fixedScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); fixedScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); horScrollBar.addAdjustmentListener(new AdjustmentListener() { @Override public void adjustmentValueChanged(AdjustmentEvent e) { fixedHorScrollBar.setValue(e.getValue()); } }); verScrollBar.addAdjustmentListener(new AdjustmentListener() { @Override public void adjustmentValueChanged(AdjustmentEvent e) { Dimension d = fixedScrollPane.getSize(); Dimension d1 = scrollPane.getSize(); } }); } public JTable getBindedTable() { return bindedTable; } } private static final long serialVersionUID = 4676303089799270571L; Object[][] data; String[] columnNames; FixedFooterTable fixedTable; JTable table; public FixedRow2Tables() { super("Fixed Row Example"); Object[][] mainData = new Object[][] { { "a", "", "", "", "", "" }, { "", "b", "", "", "", "" }, { "", "", "c", "", "", "" }, { "", "", "", "d", "", "" }, { "", "", "", "", "e", "" }, { "", "", "", "", "", "f" }, { "a", "b", "c", "d", "e", "f" }, { "a", "b", "c", "d", "e", "f" }, { "a", "b", "c", "d", "e", "f" }, { "a", "b", "c", "d", "e", "f" }, { "a", "b", "c", "d", "e", "f" } }; Object[][] summaryData = { { "fixed1", "", "", "", "", "" }, { "fixed2", "b", "c", "d", "e", "f" } }; columnNames = new String[] { "Ala", "Bardzo", "Chciala", "Dostac", "Eskimoska", "Franciszki Genowefy Pigwy" }; table = new JTable(mainData, columnNames); table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); fixedTable = new FixedFooterTable(summaryData, columnNames); fixedTable.setTableHeader(null); final JScrollPane scroll = new JScrollPane(table); final JScrollPane fixedscroll = new JScrollPane(fixedTable); Dimension preferredSize = fixedTable.getPreferredSize(); fixedscroll.setPreferredSize(preferredSize); fixedTable.bindTableModels(table); fixedTable.bindViews(scroll, fixedscroll); getContentPane().add(scroll, BorderLayout.CENTER); getContentPane().add(fixedscroll, BorderLayout.SOUTH); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { FixedRow2Tables frame = new FixedRow2Tables(); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); frame.pack(); frame.setVisible(true); } }); } }