我在JPanel上有一个JTree,它位于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 );
}
});
}
}
修改 的
可能已经破解了......将这些行添加到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或更少,调整大小不起作用...... / p>
NB显然,tree_jsp必须是最终的,并且这两行可能被添加到代码的主要部分以理解我的疯狂方法
JTable table = new JTable( 1, 2 );
left_panel.add( table, BorderLayout.EAST );
还有另一件事:我们被告知不要使用setPreferredSize ......也许上述行为可以纯粹通过使用布局来实现......?
编辑2
最终得出的结论是我的目标有点偏斜:实际上我需要左侧组件上的滚动窗格和右侧组件上的单独滚动窗格。之后,似乎不需要JSplitPane(或包含它的JPanel)上的滚动窗格:有时在容器层次结构中保持滚动窗格较低的滚动窗格无疑必须存在...但我意识到它是相当高的优先级设计出这种情况...... 我发现BorderLayout的问题确实在做我想要的...... BoxLayout和GridLayout的组合确实有帮助(这完全是在试图完全避免setXXXSize的上下文中)。毫无疑问,答案也在于试图掌握GridBagLayout ......
答案 0 :(得分: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 );
编辑:您应该始终将树添加到滚动窗格,因为这是您在没有足够空间时要滚动的内容。但是,您可以将滚动窗格添加到面板,将面板添加到splitpane:
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上使用滚动窗格,那么你只需要一个滚动窗格。拆分窗格不需要滚动窗格。只需将splitpane直接添加到框架中:
//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 );