调整双JTable中的列大小的问题

时间:2010-04-19 10:54:25

标签: java swing jtable

我正在创建一个包含2个JTable的自定义组件,一个作为主数据网格,另一个作为始终可见的摘要栏,我已经提出了这个解决方案,但调整列的工作原理不应该如此,任何想法都有我错了吗?

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);
            }
        });
    }
}

5 个答案:

答案 0 :(得分:2)

fixedTable.setColumnModel(table.getColumnModel());

问题出在那条线上。如果您将其注释掉,则表格表现正常。如果这会破坏你的代码(因为我不知道你想要做什么)只需评论。

但是,正如您在评论中添加的那样,您希望同步这两个表。我找到了一个完全涵盖该问题的论坛帖子:

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

玩得开心!

P.S。:以防论坛帖子线程消失(只是复制了文本):

首先勾选表格。不得不分享ColumnModel否则它不起作用。这些面板都有一个JTable字段,set和get 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();
}

答案 1 :(得分:1)

这段代码为我修好了。

请注意,不在表之间重用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);
            }
        });
    }
}

答案 2 :(得分:1)

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){}
}

答案 3 :(得分:1)

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

class TableHack(model: TableModel) : JXTable(model) {

    override fun columnMarginChanged(e: ChangeEvent?) {
        repaint();
        return;
    }
}

将此表用作“摘要”-table,并从主表中设置ColumnModel

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

答案 4 :(得分:0)

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

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);
            }
        });
    }
}