多个 JTable 相互叠加,就像一个 JTable

Multiple JTables on top of each other acting like one JTable

我想要 x 个 JTables 在彼此之上,就像一个 JTable 一样。我创建了 x 个单独的 JScollPanes - 每个 table 一个,并将它们全部插入到一个 JPanel (panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));) 中。

我只显示最顶部 table 的 header。为了使它们一致地水平滚动,我使用了 here.

我还需要完成两个任务才能实现它看起来像一个大 JTable 的预期结果。

  1. 我希望只有一个垂直滚动条?如何实现?

  2. 我希望所有 table 共享同一个 TableColumnModel 作为最上面的 table(这是唯一显示 header 的)因此,如果通过拖放 header 移动列,则所有 table 都会反映更改...

如果有人想知道,我以前尝试将每个 JTable 添加到一个 JPanel,然后将每个 JPanel 添加到一个 JScrollPane。该解决方案的问题是,如果其中一个 JTable 有很多条目,垂直滚动条将不会显示所有条目....

基于这个问题和你其他问题的图片,我可能有一个方法,虽然它有点 hack。

方法:

  1. 创建多个 table 并将它们添加到 JScrollPane。使用 BoxLayout

  2. 将每个滚动窗格添加到面板
  3. 第一个滚动窗格将包含并清空 table,因此只有 table header 在滚动窗格中可见。

  4. 最后一个滚动窗格将显示 JTable 和水平滚动条。

  5. 第一个和最后一个之间的任何滚动窗格将只显示 JTable。

  6. 代码使用自定义 ScrollablePanel。此面板将强制面板的宽度等于视口的宽度。这将反过来强制每个滚动窗格的水平滚动条处于活动状态。每个水平滚动条共享相同的模型,因此即使只有一个滚动条可见,所有 table 也会同时滚动。

查看 Scrollable Panel 下载代码。

这里是代码:

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

public class TableSharedHeader2 extends JPanel
{
    private JTable table1;
    private JTable table2;
    private JPanel tablePanel;

    TableSharedHeader2()
    {
        setLayout( new BorderLayout() );

        //  Only the Table Header is displayed

        JTable table0 = new JTable( 0, 10);
        table0.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
        table0.setPreferredScrollableViewportSize(table0.getPreferredSize());
        JScrollPane scrollPane0 = new JScrollPane( table0 );
        scrollPane0.setVerticalScrollBarPolicy( ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER );

        //  Only the JTable is displayed

        table1 = new JTable(5, 10);
        table1.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
        table1.setTableHeader( null );
        table1.setPreferredScrollableViewportSize(table1.getPreferredSize());
        JScrollPane scrollPane1 = new JScrollPane( table1 );
        scrollPane1.setVerticalScrollBarPolicy( ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER );

        // The JTable and the horizontal scrollbar is displayed.

        table2 = new JTable(3, 10);
        table2.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
        table2.setTableHeader( null );
        System.out.println(table0.getTableHeader());
        table2.setPreferredScrollableViewportSize(table2.getPreferredSize());
        JScrollPane scrollPane2 = new JScrollPane( table2 );
        scrollPane2.setVerticalScrollBarPolicy( ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER );
        scrollPane2.setHorizontalScrollBarPolicy( ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS );

        // share the column model with the last two tables

        table1.setColumnModel( table0.getColumnModel() );
        table2.setColumnModel( table0.getColumnModel() );

        // share the scrollbar model with the last two scrollbars

        scrollPane1.getHorizontalScrollBar().setModel( scrollPane0.getHorizontalScrollBar().getModel());
        scrollPane2.getHorizontalScrollBar().setModel( scrollPane0.getHorizontalScrollBar().getModel());

        //  hide the scrollbars of the first two tables.

        scrollPane0.getHorizontalScrollBar().setPreferredSize( new Dimension(0, 0) );
        scrollPane1.getHorizontalScrollBar().setPreferredSize( new Dimension(0, 0) );

        // add components to the panel

        tablePanel = new JPanel();
        ScrollablePanel tablePanel = new ScrollablePanel();
        tablePanel.setScrollableWidth( ScrollablePanel.ScrollableSizeHint.FIT );
        tablePanel.setLayout( new BoxLayout(tablePanel, BoxLayout.Y_AXIS) );
        tablePanel.add( scrollPane0 );
        tablePanel.add( new JLabel("First Label") );
        tablePanel.add( scrollPane1 );
        tablePanel.add( new JLabel("Second Label") );
        tablePanel.add( scrollPane2 );

        JScrollPane scrollPane = new JScrollPane( tablePanel );
        scrollPane.setHorizontalScrollBarPolicy( ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER );
        add( scrollPane );

    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("TableSharedHeader2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new TableSharedHeader2());
        frame.pack();
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater( () -> createAndShowGUI() );
/*
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
*/
    }
}

经过camickr的大力帮助和指导,这里是代码解决方案。

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

public class TableSharedHeader2 extends JPanel
{
    private JTable table1;
    private JTable table2;
    private JPanel tablePanel;

    TableSharedHeader2()
    {
        setLayout( new BorderLayout() );

        //  Only the Table Header is displayed

        JTable table0 = new JTable( 0, 10);
        table0.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
        table0.setPreferredScrollableViewportSize(table0.getPreferredSize());
        JScrollPane scrollPane0 = new JScrollPane( table0 );
        scrollPane0.setVerticalScrollBarPolicy( ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER );

        //  Only the JTable is displayed

        table1 = new JTable(5, 10);
        table1.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
        table1.setTableHeader( null );
        table1.setPreferredScrollableViewportSize(table1.getPreferredSize());
        JScrollPane scrollPane1 = new JScrollPane( table1 );
        scrollPane1.setVerticalScrollBarPolicy( ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER );

        // The JTable and the horizontal scrollbar is displayed.

        table2 = new JTable(60, 10);
        table2.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
        table2.setTableHeader( null );
        System.out.println(table0.getTableHeader());
        table2.setPreferredScrollableViewportSize(table2.getPreferredSize());
        JScrollPane scrollPane2 = new JScrollPane( table2 );
        scrollPane2.setVerticalScrollBarPolicy( ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER );
         scrollPane2.setHorizontalScrollBarPolicy( ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER );

        // share the column model with the last two tables

        table1.setColumnModel( table0.getColumnModel() );
        table2.setColumnModel( table0.getColumnModel() );

        // share the scrollbar model with the last two scrollbars

        scrollPane1.getHorizontalScrollBar().setModel( scrollPane0.getHorizontalScrollBar().getModel());
        scrollPane2.getHorizontalScrollBar().setModel( scrollPane0.getHorizontalScrollBar().getModel());

        //  hide the scrollbars of the first two tables.

        scrollPane0.getHorizontalScrollBar().setPreferredSize( new Dimension(0, 0) );
        scrollPane1.getHorizontalScrollBar().setPreferredSize( new Dimension(0, 0) );

        // add components to the panel

        tablePanel = new JPanel();
        ScrollablePanel tablePanel = new ScrollablePanel();
        tablePanel.setScrollableWidth( ScrollablePanel.ScrollableSizeHint.FIT );

        //changed this to stretch for Vertical Scroll Bar to appear if frame is resized and data can not fit in viewport
        tablePanel.setScrollableHeight( ScrollablePanel.ScrollableSizeHint.STRETCH );
        tablePanel.setLayout( new BoxLayout(tablePanel, BoxLayout.Y_AXIS) );

        tablePanel.add( new JLabel("First Label") );
        tablePanel.add( scrollPane1 );
        tablePanel.add( new JLabel("Second Label") );
        tablePanel.add( scrollPane2 );

        JScrollPane scrollPane = new JScrollPane( tablePanel );
        JScrollBar bar = scrollPane2.getHorizontalScrollBar();

    //this removes mouse wheel listeners from all the inner scrollpanes and
   //allows the main scrollpane (scrollPane) to react to mousewheel
        scrollPane0.removeMouseWheelListener(scrollPane0.getMouseWheelListeners()[0]);
        scrollPane1.removeMouseWheelListener(scrollPane1.getMouseWheelListeners()[0]);
        scrollPane2.removeMouseWheelListener(scrollPane2.getMouseWheelListeners()[0]);

        // Add header to top of border layout
        add(scrollPane0,BorderLayout.PAGE_START);

        //add main tablePanel which has JTables (no headers) and labels to body of border layout
        add( scrollPane,BorderLayout.CENTER );

        //add bottom scollpane (scrollpane2) scroll bar to bottom of border layout 
        add(bar,BorderLayout.PAGE_END);
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("TableSharedHeader2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new TableSharedHeader2());
        frame.pack();
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater( () -> createAndShowGUI() );
/*
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
*/
    }
}