【问题标题】:Multiple JTables on top of each other acting like one JTable多个 JTable 相互叠加,就像一个 JTable
【发布时间】:2020-05-27 19:11:43
【问题描述】:

我希望将 x 个 JTable 叠放在一起,就像一个 JTable。我创建了 x 个单独的 JScollPanes - 每个表一个,并将它们全部插入一个 JPanel (panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));)。

我只显示最顶层表格的标题。为了实现它们一致的水平滚动,我使用了here

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

  1. 我希望只有一个垂直滚动条?如何做到这一点?

  2. 我希望所有表共享相同的 TableColumnModel 作为最顶部的表(这是唯一显示标题的表),因此如果通过拖放标题移动列,所有表都会反映更改。 ..

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

【问题讨论】:

  • 我不确定您要完成什么,但您的方法听起来很奇怪,超出了 JTable 实际打算做的范围。为什么你甚至想要使用多个 JTable,而不仅仅是一个?
  • @Taschi:我认为 OP 正在寻找一种通常称为手风琴的组件。没有任何 Swing 组件可以满足 OP 的要求;但是,他可以创建一个或在 Internet 上找到一个。

标签: java swing jtable jscrollpane


【解决方案1】:

根据这个问题和你其他问题的图片,我可能有一个方法,虽然它有点像黑客。

方法:

  1. 创建多个表并将它们添加到 JScrollPane。使用 BoxLayout 将每个滚动窗格添加到面板

  2. 第一个滚动窗格将包含并清空表格,因此只有表格标题在滚动窗格中可见。

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

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

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

查看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();
            }
        });
*/
    }
}

【讨论】:

  • 感谢您的帮助。我们越来越近了。我试过你的代码,它看起来很棒,除了两个问题...... 1.)标题在垂直滚动时消失,2.)当使用鼠标滚轮滚动时,垂直滚动条不会在可滚动面板上自动激活......
    任何想法如何解决这两个问题?
  • 我们已经非常接近了 - 那么您尝试了什么? 1)第一个表应该只用于提供标题和滚动条。然后您可以将表格标题移动到面板的 BorderLayout.PAGE_START 和滚动条到面板的 BorderLayout.PAGE_END,因为它使用的是 BorderLayout。然后可以以相同的方式配置另外两个表,因为只有 JTable 本身将添加到 tablePanel。 2)滚轮滚动鼠标下的滚动窗格。
  • 有一个小问题....从发生? ——
【解决方案2】:

这是在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();
            }
        });
*/
    }
}

【讨论】:

  • 有一个小问题....不会发生?
  • 或许值得提出一个新问题?或者在 camickr 的答案的评论部分询问它,以便他在那里收到关于您的问题的警报。
  • 所有数据都适合并垂直拉伸框架,在 BorderFactory.CENTER 中列出的组件之间创建白色(灰色)空间。 - 这是一个布局问题。不要将 BorderLayout 用于顶级布局。也许试试另一个垂直的 BoxLayout?
  • 哪种布局确保列标题被冻结在顶部? (意味着他们有一个 PAGE_START 和 PAGE_END 属性或类似的东西)
猜你喜欢
  • 2011-10-25
  • 1970-01-01
  • 2015-03-20
  • 1970-01-01
  • 2020-09-29
  • 1970-01-01
  • 2015-03-18
  • 2014-05-03
  • 1970-01-01
相关资源
最近更新 更多