0

我在 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 或更少,则调整大小不起作用......

注意,tree_jsp 也必须是最终的,显然,这两行可能会添加到代码的主要部分以理解我疯狂的方法

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

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

编辑 2

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

4

1 回答 1

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来告诉滚动窗格将添加到滚动窗格的组件的高度固定为滚动窗格的高度。有关帮助程序类,请参阅可滚动面板。使用此类,您的代码将是:

//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 );
于 2013-09-11T17:19:07.670 回答