【问题标题】:make JScrollPane lower in hierarchy resize when JFrame does当 JFrame 调整大小时,使 JScrollPane 在层次结构中降低
【发布时间】:2013-09-11 17:11:14
【问题描述】:

我在 JScrollPane 上的 JPanel 上有一个 JTree,它是 JSplitPane 的左侧组件。 JSplitPane 在它自己的 JScrollPane 上。后者不允许显示其垂直滚动条...相反,每当调整 JFrame 的大小以使某些树看不见时,我希望树面板的垂直滚动条启动...

换句话说,我希望树的滚动窗格的视口始终与框架的内容窗格的高度相同......我已经尝试过各种实验

这是一个 SSCCE:

import java.awt.*;
import java.awt.event.ComponentEvent;
import java.lang.reflect.InvocationTargetException;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;


public class Packing {
  public static void main( String[] args ) throws InterruptedException, InvocationTargetException{
    EventQueue.invokeLater( new Runnable(){
      @Override
      public void run() {
        JTree jt = new JTree();
        DefaultTreeModel model = (DefaultTreeModel)jt.getModel();
        for( int i = 0; i < 30; i++ ){
          model.insertNodeInto( new DefaultMutableTreeNode( i ), 
              (DefaultMutableTreeNode)model.getRoot(), 0 );
        }


        JPanel left_panel = new JPanel();
        left_panel.setLayout( new BorderLayout() );
        left_panel.add( jt, BorderLayout.WEST );
        JScrollPane tree_jsp = new JScrollPane( left_panel );


        JSplitPane split_pane = new JSplitPane();
        split_pane.setDividerLocation( 0.5d );
        split_pane.setLeftComponent( tree_jsp );
        JScrollPane split_jsp = new JScrollPane( split_pane );
        split_jsp.setVerticalScrollBarPolicy( ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER );


        JFrame frame = new JFrame( "Resizing prob" );
        frame.getContentPane().add( split_jsp );
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.addComponentListener(new java.awt.event.ComponentAdapter() {
          public void componentResized(ComponentEvent e) {
            System.out.println( ">>> frame resized" );
          }
        });
        frame.pack();
        frame.setVisible( true );
      }
    });
  }
}

编辑

可能已经破解了...将这些行添加到 componentResized:

  int vp_width = tree_jsp.getViewport().getSize().width;
  tree_jsp.getViewport().setPreferredSize( 
            new Dimension( vp_width, frame.getContentPane().getSize().height - 40 ));
  tree_jsp.getViewport().validate();

显然这是一个粗略的草案... 40 数字是一个奇怪的数字,我试图理解...在我的机器上,如果这个数字设置为 20 或更少,则调整大小不起作用...

NB 还必须将 tree_jsp 设置为 final,显然,这两行可能会添加到代码的主要部分中以理解我疯狂的方法

  JTable table = new JTable( 1, 2 );
  left_panel.add( table, BorderLayout.EAST );

还有一件事:我们被告知不要使用 setPreferredSize...也许上述行为可以纯粹通过使用布局来实现...?

编辑 2

最后得出的结论是,我的目标有点偏差:我确实需要左侧组件上的滚动窗格和右侧组件上的单独滚动窗格。在那之后,似乎不需要在 JSplitPane(或包含它的 JPanel)上使用滚动窗格:在容器层次结构中保持滚动窗格较低的滚动窗格无疑有时必须存在......但我意识到这是一个相当高的优先级设计这种情况... 我发现 BorderLayout 确实在做我想做的事情...... BoxLayout 和 GridLayout 的组合确实有帮助(这都是在试图完全避免 setXXXSize 的背景下)。毫无疑问,答案还在于尝试掌握 GridBagLayout...

【问题讨论】:

    标签: java swing resize jscrollpane jtree


    【解决方案1】:

    摆脱面板。只需将 JTree 添加到 JScrollPane:

    //        JPanel left_panel = new JPanel();
    //        left_panel.setLayout( new BorderLayout() );
    //        left_panel.add( jt, BorderLayout.WEST );
    //        JScrollPane tree_jsp = new JScrollPane( left_panel );
            JScrollPane tree_jsp = new JScrollPane( jt );
    

    编辑:您应该始终将树添加到滚动窗格,因为这是您在空间不足时想要滚动的内容。但是您可以随后将滚动窗格添加到面板并将面板添加到拆分窗格:

        JScrollPane tree_jsp = new JScrollPane( jt );
    
        JPanel left_panel = new JPanel();
        left_panel.setLayout( new BorderLayout() );
        left_panel.add( tree_jsp, BorderLayout.WEST );
    
        JSplitPane split_pane = new JSplitPane();
        split_pane.setDividerLocation( 0.5d );
        // split_pane.setLeftComponent( tree_jsp );
        split_pane.setLeftComponent( left_panel );
    

    Edit2:如果您只想要 lef_panel 上的滚动窗格,那么您只需要一个滚动窗格。拆分窗格不需要滚动窗格。只需将拆分窗格直接添加到框架中即可:

    //frame.getContentPane().add( split_jsp );
    frame.add( split_pane );
    

    这种方法可能会导致 JTable 出现问题,因为总是希望将表格添加到滚动窗格中,因为这是显示表格标题的最简单方法。

    另外,从JDK5开始你就不需要getContentPane()方法了,框架会为你添加组件到内容窗格中。

    编辑 3:您可以使用 Scollable interface 来告诉滚动窗格将添加到滚动窗格的组件的高度固定为滚动窗格的高度。请参阅 Scrollable Panel 以获取帮助程序类。使用此类,您的代码将是:

    //JScrollPane split_jsp = new JScrollPane( split_pane );
    //split_jsp.setVerticalScrollBarPolicy( ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER );
    
    ScrollablePanel scrollable = new ScrollablePanel( new BorderLayout() );
    scrollable.setScrollableHeight( ScrollablePanel.ScrollableSizeHint.FIT );
    scrollable.setScrollableWidth( ScrollablePanel.ScrollableSizeHint.STRETCH );
    scrollable.add(split_pane);
    JScrollPane split_jsp = new JScrollPane( scrollable );
    

    【讨论】:

    • 谢谢...我知道这行得通...但实际上需要 JPanel,因为要添加其他东西...特别是 JTable,它将动态调整大小以具有相同的作为 JTree 的行数,将是 JPanel 中的 EAST 组件
    • @mikerodent,见编辑。并且您的表格也需要添加到单独的滚动窗格中。
    • 好的,谢谢你的想法......那么两个滚动窗格(树和表格)将不得不被束缚在一起,这似乎有点不雅,因为它们完全同步......但我只是想知道当框架改变大小时是否没有设置视口大小的机制(因此是组件监听器)......?
    • 再次感谢。问题是我确实需要拆分窗格的(水平)滚动条......确实我的想法是,在解决了这个棘手的问题之后,我会继续建立拆分窗格的滚动窗格的最小高度,低于它 显示它自己的垂直滚动条。我理解关于 JTable 的要点:事实上,我之前的问题是关于当 JTable 的网格线不包含在滚动窗格中时,其网格线的绘制相当不令人满意。我仍在寻找一种有意识地控制视口高度的方法!
    • 谢谢...我被告知不要再添加任何 cmets,所以我一定会在 ScrollablePanel 上查看您的页面,并感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-16
    • 1970-01-01
    相关资源
    最近更新 更多