Footer row in a JTable

前端 未结 8 1503
感动是毒
感动是毒 2020-12-20 22:26

What is the best way to put a footer row into a JTable? Does anyone have any sample code to do this?

The only approach I\'ve thought of so far is to put a special ro

相关标签:
8条回答
  • 2020-12-20 22:29

    You could try implementing your own TableCellRenderer that replaces the rendered content of the last visible row with your footer. However this wouldn't be fixed at the bottom of the table, it will likely shift up and down as you scroll.

    0 讨论(0)
  • 2020-12-20 22:30
    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){}
    }
    
    0 讨论(0)
  • 2020-12-20 22:37

    Looks like this project has a component called JideScrollPane which advertises support for a row footer. I haven't tried it myself, but it sounds like it does exactly what you want! The website also has a demo app where you can see it in action and it that looks pretty good.

    Note that it seems a lot of the their stuff you have to pay for, but their JideScrollPane looks to be free and open source.

    0 讨论(0)
  • The only time I have done this I just added a row in the model like so:

        @Override
        public int getRowCount() {
            return _tableContents.size() + 1;
        }
    

    _tableContents is of course the actual data behind my model. You'll have to be aware of the extra row in the model of course (in such calls as setValueAt(...))

    Good luck.

    0 讨论(0)
  • 2020-12-20 22:49

    Using 2 tables below each-other is a good approach.

    If you want to be able to resize/move/remove the colums, key is NOT to reuse the same columnModel between the tables. Have a listener do the resizing. See example:

    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);
                }
            });
        }
    }
    
    0 讨论(0)
  • 2020-12-20 22:50

    Try using a second JTable that uses the same column model as your data table and add your footer data to that table. Add the second (footer) table under your original table.

    JTable footer = new JTable(model, table.getColumnModel());
    panel.add(BorderLayout.CENTER, table);
    panel.add(BorderLayout.SOUTH, footer);
    
    0 讨论(0)
提交回复
热议问题