Java 当JFrame调整时,使JScrollPane在层次结构中处于较低的位置

Java 当JFrame调整时,使JScrollPane在层次结构中处于较低的位置,java,swing,resize,jscrollpane,jtree,Java,Swing,Resize,Jscrollpane,Jtree,我在JPanel上有一个JTree,它位于JScrollPane上,JScrollPane是JSplitPane的左侧组件。JSplitPane位于其自己的JScrollPane上。后者不允许显示其垂直滚动条。。。相反,无论何时调整JFrame的大小,使树的某些部分消失在视野之外,我都希望树面板的垂直滚动条进入 换句话说,我希望树的滚动窗格的视口始终与框架的内容窗格的高度相同。。。我已经尝试过这些方面的各种实验 以下是SSCCE: import java.awt.*; import java.a

我在JPanel上有一个JTree,它位于JScrollPane上,JScrollPane是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 );
      }
    });
  }
}
显然这是一个粗略的草案。。。40这个数字是一个奇怪的数字,我正试图去理解。。。在我的机器上,如果此数字设置为20或更少,则调整大小不起作用

很明显,tree_jsp也必须是最终的,这两行代码可能会添加到主要代码中,以理解我发疯时的方法

  JTable table = new JTable( 1, 2 );
  left_panel.add( table, BorderLayout.EAST );
还有一件事:我们被告知不要使用setPreferredSize。。。也许上述行为完全可以通过使用布局来实现

编辑2

最后得出的结论是,我的目标有点偏斜:实际上,我需要在左侧组件上有一个滚动窗格,在右侧组件上有一个单独的滚动窗格。在这之后,在JSplitPane(或包含它的JPanel)上似乎就不需要滚动窗格了:在容器层次结构中保持滚动窗格较低的滚动窗格无疑有时必须存在。。。但我意识到设计这种情况是非常重要的。。。
我发现BorderLayout在做我想做的事情时有问题。。。BoxLayout和GridLayout的组合真的很有帮助(这都是在试图完全避免setXXXSize的情况下)。毫无疑问,答案还在于努力掌握GridBagLayout…

摆脱面板。只需将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_面板上有一个滚动窗格,那么你只需要一个滚动窗格。拆分窗格不需要滚动窗格。只需将拆分窗格直接添加到框架:

//frame.getContentPane().add( split_jsp );
frame.add( split_pane );
这种方法可能会导致JTable出现问题,因为人们总是希望将表添加到滚动窗格中,因为这是显示表头的最简单方法

此外,您不需要getContentPane()方法,因为JDK5框架将为您向内容窗格添加组件

编辑3:您可以使用
Scollable界面告诉滚动窗格将添加到滚动窗格的组件的高度固定为滚动窗格的高度。有关帮助器类,请参见。使用此类,您的代码将是:

//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@mikerodent,请参见编辑。您的表格还需要添加到单独的滚动窗格中。好的,谢谢您的想法。。。然后,两个滚动窗格(树和表)将不得不被捆绑在一起,这似乎不雅观,因为他们是在完美的同步。。。但我只是想知道,当帧改变大小时,是否没有一种机制来设置视口的大小(因此组件侦听器)?再次感谢。问题是我确实需要一个(水平)滚动条来显示拆分窗格。。。事实上,我的想法是,在解决了这个棘手的问题之后,我将继续建立splitpane滚动窗格的最小高度,在该高度下它将显示自己的垂直滚动条。我理解JTable的要点:事实上,我之前的问题是关于JTable的网格线在不包含在滚动窗格中的情况下绘制得相当不令人满意。我仍在寻找有意识地控制视口高度的方法!谢谢我被告知不要再添加任何评论,所以我一定会在ScrollablePanel上查看您的页面,谢谢您的帮助!
//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 );