如何使用分割窗格

JSplitPane显示两个组件,两个组件并排显示,一个显示在另一个组件的上面。通过拖动出现在组件之间的分隔线,用户可以指定分割窗格的总面积中有多少分配给每个组件。您可以通过将拆分窗格放在拆分窗格中来在三个或更多组件之间划分屏幕空间,如嵌套拆分窗格所述。

经常将每个组件放入scroll pane,而不是将感兴趣的组件直接添加到拆分窗格中。然后,将滚动窗格放入拆分窗格。这允许用户查看感兴趣的组件的任何部分,而无需该组件占用大量屏幕空间或适应于以各种屏幕空间显示自己。

这是一个使用拆分窗格显示并排显示列表和图像的应用程序的图片:

SplitPaneDemo 快照

Try this:

  • 单击启动按钮以使用Java™Web 开始(下载 JDK 7 或更高版本)运行 SplitPaneDemo。另外,要自己编译和运行示例,请查阅example index

  • 将将列表和图像分开的虚线线向左或向右拖动。try将分隔线一直拖动到窗口的边缘。

  • 单击分隔线上的细箭头,以隐藏/展开左侧或右侧组件。

以下是来自SplitPaneDemo的代码,用于创建和设置拆分窗格。

//Create a split pane with the two scroll panes in it.
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                           listScrollPane, pictureScrollPane);
splitPane.setOneTouchExpandable(true);
splitPane.setDividerLocation(150);

//Provide minimum sizes for the two components in the split pane
Dimension minimumSize = new Dimension(100, 50);
listScrollPane.setMinimumSize(minimumSize);
pictureScrollPane.setMinimumSize(minimumSize);

本示例使用的构造函数带有三个参数。第一个指示分割方向。其他参数是放置在拆分窗格中的两个组件。有关可动态设置组件的JSplitPane方法的信息,请参考在拆分窗格中设置组件

在此示例中,拆分窗格被水平拆分-两个组件并排出现-由构造函数的JSplitPane.HORIZONTAL_SPLIT参数指定。拆分窗格提供了另一个选项,用JSplitPane.VERTICAL_SPLIT指定,该选项将一个组件放置在另一个组件之上。使用setOrientation方法创建拆分窗格后,可以更改拆分方向。

在示例的拆分窗格中,分隔线的顶部出现两个小箭头。这些箭头使用户只需单击即可折叠(然后展开)任何一个组件。当前的外观决定这些控件是否默认显示。在 Java 外观中,它们默认情况下处于关闭状态。 (请注意,并非所有的外观都支持此功能.)本示例使用setOneTouchExpandable方法将其启用。

拆分窗格的分隔符的范围部分取决于拆分窗格中组件的最小大小。有关详情,请参见放置分频器并限制其范围

本节的其余部分涵盖以下主题:

在拆分窗格中设置组件

程序可以使用以下四种方法动态设置拆分窗格的两个组件:

  • setLeftComponent

  • setRightComponent

  • setTopComponent

  • setBottomComponent

无论拆分窗格当前的拆分方向如何,都可以随时使用这些方法中的任何一种。调用setLeftComponentsetTopComponent是等效的,并将指定的组件设置在顶部或左侧,具体取决于拆分窗格的当前拆分方向。同样,对setRightComponentsetBottomComponent的调用是等效的。这些方法用新的方法替换了已经处于该位置的任何部件。

像其他容器一样,JSplitPane支持add方法。拆分窗格将添加的第一个组件放在左侧或顶部。使用add的危险是您可能无意中多次调用它,在这种情况下,拆分窗格的布局 管理 器将抛出一个看起来很深奥的异常。如果使用add方法,并且已经填充了拆分窗格,则首先需要使用remove删除现有组件。

如果仅在拆分窗格中放置一个组件,则分隔符将卡在拆分窗格的右侧或底部,具体取决于拆分方向。

放置分频器并限制其范围

为了使拆分窗格正常工作,通常需要在拆分窗格中设置组件的最小大小,以及拆分窗格或其包含的组件的首选大小。选择应该设置的大小是一门艺术,需要了解如何确定分割窗格的首选大小和分隔线位置。在详细介绍之前,让我们再看一下 SplitPaneDemo。或者,如果您赶时间,可以跳到规则清单

Try this:

因为演示帧的大小是使用pack方法设置的,所以拆分窗格处于其首选大小,而 SplitPaneDemo 恰好是明确设置的。分隔线会自动放置,以使左侧组件处于其首选宽度,所有剩余空间都移至右侧组件。

  • 扩大窗口。
    分隔线停留在原来的位置,多余的空间移到右侧的组件。

  • 使窗口明显比第一次出现时窄-可能是左部分的两倍。
    同样,左侧组件的大小和分隔线位置保持不变。仅正确组件的大小会更改。

  • 使窗口尽可能窄。
    假设窗口使用 Java 外观提供的装饰,则窗口的大小不能小于拆分窗格的最小大小,该最小大小由拆分窗格所包含的组件的最小大小确定。 SplitPaneDemo 显式设置这些包含的组件的最小大小。

  • 使窗口变宽,然后将分隔线拖动到最右边。
    分压器仅在正确组件的最小尺寸允许的范围内移动。如果将分隔线拖动到左侧,您会看到它也遵守左侧组件的最小尺寸。

现在,您已经看到了拆分窗格的默认行为,我们可以告诉您幕后发生的事情以及如何影响它。在此讨论中,当我们指的是组件的首选或最小尺寸时,如果分割窗格是水平的,则通常是指组件的首选或最小宽度;如果分割窗格是垂直的,则通常是指组件的首选或最小高度。

默认情况下,将初始化拆分窗格的首选大小和分隔符位置,以使拆分窗格中的两个组件处于首选大小。如果未以此首选大小显示拆分窗格,并且程序未明确设置分隔线的位置,则分隔线的初始位置(以及两个组件的大小)取决于名为的拆分窗格属性。调整重量。如果分割窗格最初是其首选尺寸或更大,则在调整调整大小权重之前,所包含的组件将以其首选尺寸开始。如果分割窗格最初太小而无法以其首选尺寸显示两个组件,则在调整调整大小权重之前,它们以“最小”尺寸开始。

拆分窗格的调整大小权重的值介于 0.0 到 1.0 之间,并确定在设置拆分窗格的大小时如何在两个包含的组件之间分配空间,无论是通过编程方式还是通过用户调整拆分窗格的大小(例如,放大其包含的窗口) 。默认情况下,拆分窗格的调整大小权重为 0.0,表示左侧或顶部组件的大小是固定的,右侧或底部组件将调整其大小以适合剩余空间。将调整大小权重设置为 0.5 会在两个组件之间平均分配任何多余或缺少的空间。将调整大小权重设置为 1.0 可使右侧或底部组件的大小保持固定。但是,当用户拖动分隔线时,调整大小的权重无效。

用户可以将分隔器拖动到任何位置,只要所含组件均不低于其最小尺寸即可。如果分隔器具有一键式按钮,则用户可以使用它们使分隔器完全移至一侧或另一侧-无论组件的最小尺寸是多少。

现在您已经知道影响拆分窗格的大小和分隔符位置的因素,以下是一些使它们正常运行的规则:

  • 为确保在拆分窗格处于其首选大小时可以拖动分隔线,请确保其中一个或两个组件的最小大小小于所包含组件的首选大小。您可以通过在组件上调用setMinimumSize或重写其getMinimumSize方法来设置组件的最小大小。例如,如果您希望用户能够将分隔线一直拖动到两侧:
Dimension minimumSize = new Dimension(0, 0);
leftComponent.setMinimumSize(minimumSize);
rightComponent.setMinimumSize(minimumSize);
  • 为确保同时显示两个包含的组件,请确保拆分窗格最初等于或大于其首选大小,或者包含的组件的最小大小大于零。

如果为拆分窗格指定了首选大小,通常会发生这种情况,这取决于包含拆分窗格的布局 管理 器。另一个选择是在拆分窗格上显式设置一个首选大小,该大小要大于所包含组件的大小。

  • 如果要在拆分窗格变大时使底部或右侧组件的大小保持相同,并使顶部或左侧组件保持灵活,则将调整大小权重设置为 1.0. 您可以通过调用setResizeWeight来做到这一点:
splitPane.setResizeWeight(1.0);
  • 如果要分割窗格的两个部分在分割窗格的额外或删除的空间中共享,请将调整大小的权重设置为 0.5:
splitPane.setResizeWeight(0.5);
  • 确保拆分窗格中包含的每个组件都具有合理的首选大小。如果组件是使用布局 管理 器的面板,则通常只能使用其返回的值。如果组件是滚动窗格,则有几种选择。您可以在滚动窗格上调用setPreferredSize方法,在滚动窗格上的组件上调用适当的方法(例如JListJTreesetVisibleRowCount方法)。

  • 确保拆分窗格中包含的每个组件都可以在不同的空间中合理地显示自己。例如,包含多个组件的面板应使用布局 管理 器,以合理的方式使用额外的空间。

  • 如果要将包含的组件的大小设置为首选大小以外的其他大小,请使用setDividerLocation方法。例如,要使左部分宽 150 像素,请执行以下操作:

splitPane.setDividerLocation(150 + splitPane.getInsets().left);

尽管拆分窗格会尽最大努力遵守初始分隔符位置(在这种情况下为 150),但是一旦用户拖动分隔符,就可能无法再拖动到以编程方式指定的大小。

要使正确的组件宽 150 像素,请执行以下操作:

splitPane.setDividerLocation(splitPane.getSize().width
                             - splitPane.getInsets().right
                             - splitPane.getDividerSize()
                             - 150);

如果拆分窗格已经可见,则可以将分隔符位置设置为拆分窗格的百分比。例如,要使 25%的空间移到左/上,请执行以下操作:

splitPane.setDividerLocation(0.25);

请注意,这是根据当前大小实现的,因此,如果可见拆分窗格,它实际上仅有用。

  • 要布置拆分窗格,就像它刚出现一样,可能会在过程中重新放置分隔符,请在拆分窗格上调用resetToPreferredSizes()

Note:

即使更改包含的组件的首选大小(即使您随后调用revalidate)也不足以导致拆分窗格再次布局。您还必须调用resetToPreferredSizes

以下快照显示了一个名为 SplitPaneDividerDemo 的示例,该示例演示了拆分窗格组件的大小和分隔线的位置。

SplitPaneDividerDemo 快照

与 SplitPaneDemo 一样,SplitPaneDividerDemo 具有一个带有一键式按钮的水平拆分窗格。 SplitPaneDividerDemo 具有以下附加功能:

  • 拆分窗格的“调整大小权重”已明确设置(为 0.5)。

  • 拆分窗格以其默认的首选大小显示。

  • 窗口底部的“重置”按钮将调用拆分窗格上的resetToPreferredSizes

  • 拆分窗格中的组件是名为SizeDisplayer的自定义JComponent子类的实例。 SizeDisplayer在褪色(也是可选)图像的背景下显示可选文本。更重要的是,它具有显示其首选和最小尺寸的矩形。

  • SplitPaneDividerDemo 将其SizeDisplayer设置为具有相同的首选大小(由于它们显示的图像大小相等),但是最小大小不相等。

Try this:

由于演示帧的大小是使用pack方法设置的,因此拆分窗格处于其首选大小,默认情况下,该大小刚好足以使SizeDisplayer处于其首选大小。每个SizeDisplayer的首选大小用红色矩形表示。分隔线会自动放置,以便两个组件都处于其首选宽度。

  • 扩大窗口。
    由于拆分窗格的调整大小权重为 0.5,因此多余的空间在左右组件之间平均分配。分隔线相应移动。

  • 使窗口尽可能窄。
    假设窗口使用 Java 外观提供的装饰,则不会使窗口的大小小于拆分窗格的最小大小,该最小大小由其所包含的SizeDisplayers的最小大小确定。每个SizeDisplayer的最小尺寸由亮蓝色矩形表示。

  • 使窗口稍微宽一点,然后将分隔线拖动到最右边。
    分压器仅在正确组件的最小尺寸允许的范围内移动。

  • 确保拆分窗格小于其首选大小后,单击“重置”按钮。
    请注意,即使应用程序启动时,两个SizeDisplayer的大小也不同,即使它们的大小相同。原因是,尽管它们的首选大小相等,但它们的最小大小却不相等。由于拆分窗格无法以首选尺寸或更大的尺寸显示它们,因此会使用其最小尺寸进行布局。剩余空间在组件之间平均分配,因为拆分窗格的调整大小权重为 0.5.

  • 加宽分割窗格,使其足够大以使两个SizeDisplayer都能以其首选大小显示,然后单击“重置”按钮。
    分隔线再次放置在中间,因此两个组件的大小相同。

这是为 SplitPaneDividerDemo 创建 GUI 的代码:

public class SplitPaneDividerDemo extends JPanel ... {

    private JSplitPane splitPane;
   
    public SplitPaneDividerDemo() {
        super(new BorderLayout());

        Font font = new Font("Serif", Font.ITALIC, 24);

        ImageIcon icon = createImageIcon("images/Cat.gif");
        SizeDisplayer sd1 = new SizeDisplayer("left", icon);
        sd1.setMinimumSize(new Dimension(30,30));
        sd1.setFont(font);
        
        icon = createImageIcon("images/Dog.gif");
        SizeDisplayer sd2 = new SizeDisplayer("right", icon);
        sd2.setMinimumSize(new Dimension(60,60));
        sd2.setFont(font);
        
        splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                                   sd1, sd2);
        splitPane.setResizeWeight(0.5);
        splitPane.setOneTouchExpandable(true);
        splitPane.setContinuousLayout(true);

        add(splitPane, BorderLayout.CENTER);
        add(createControlPanel(), BorderLayout.PAGE_END);
    }
    ...
}

该代码是很容易解释的,除了可能调用setContinuousLayout。将* continuousLayout *属性设置为 true 可在用户移动分隔线时连续绘制拆分窗格的内容。默认情况下,连续布局未启用,因为它会对性能产生负面影响。但是,在此演示中使用它是有意义的,当使拆分窗格的组件尽可能最新时,可以改善用户体验。

嵌套拆分窗格

这是一个程序的图片,该程序通过将一个拆分窗格嵌套在另一个拆分窗格中来实现三向拆分:

SplitPaneDemo2 的快照

如果您熟悉拆分窗格的顶部,那是因为该程序将SplitPaneDemo创建的拆分窗格放置在第二个拆分窗格中。简单的JLabel是第二个拆分窗格中的另一个组件。这不是嵌套拆分窗格的最实际用途,但可以理解这一点。

这是代码中有趣的部分,您可以在SplitPaneDemo2.java中找到:

//Create an instance of SplitPaneDemo
SplitPaneDemo splitPaneDemo = new SplitPaneDemo();
JSplitPane top = splitPaneDemo.getSplitPane();

...
//Create a regular old label
label = new JLabel("Click on an image name in the list.",
                   JLabel.CENTER);

//Create a split pane and put "top" (a split pane)
//and JLabel instance in it.
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
                                      top, label);

有关解决在嵌套拆分窗格时可能出现的边框问题的信息,请参阅解决常见组件问题

拆分窗格 API

下表列出了常用的JSplitPane构造函数和方法。您最有可能在JSplitPane对象上调用的其他方法是其超类提供的诸如setPreferredSize之类的方法。有关常用继承方法的表,请参见JComponent API

使用列表的 API 分为以下几类:

设置拆分窗格

方法或构造函数Purpose
JSplitPane()

JSplitPane(int)
JSplitPane(int, boolean)
JSplitPane(int,Component,Component)
JSplitPane(int,boolean,Component,Component)
创建一个拆分窗格。 int参数(如果存在)指示拆分窗格的方向,即HORIZONTAL_SPLIT(默认)或VERTICAL_SPLITboolean参数(如果存在)设置用户拖动分割窗格时组件是否连续重绘。如果未指定,则关闭此选项(称为* continuous layout *)。 Component参数分别设置初始的左侧和右侧或顶部和底部分量。
void setOrientation(int)
int getOrientation()
设置或获取拆分窗格的方向。使用JSplitPane中定义的HORIZONTAL_SPLITVERTICAL_SPLIT。如果未指定,则拆分窗格将水平拆分。
void setDividerSize(int)
int getDividerSize()
设置或获取分隔线的大小(以像素为单位)。
void setContinuousLayout(boolean)
boolean isContinuousLayout()
设置或获取在用户拖动分隔线时是否连续布置和绘制分割窗格的组件。默认情况下,连续布局是关闭的。
void setOneTouchExpandable(boolean)
boolean isOneTouchExpandable()
设置或获取拆分窗格是否在分隔符上显示控件以展开/折叠分隔符。默认值取决于外观。在 Java 外观中,默认情况下处于禁用状态。

管理 拆分窗格的内容

MethodPurpose
void setTopComponent(Component)

void setBottomComponent(Component)
void setLeftComponent(Component)
void setRightComponent(Component)
Component getTopComponent()
Component getBottomComponent()
Component getLeftComponent()
Component getRightComponent()
设置或获取指示的组件。不管拆分窗格的方向如何,每种方法都有效。顶部和左侧是等效的,底部和右侧是等效的。
void remove(Component)
void removeAll()
从拆分窗格中删除指示的组件。
void add(Component)将组件添加到拆分窗格。您只能将两个组件添加到拆分窗格中。添加的第一个组件是顶部/左侧组件。添加的第二个组件是底部/右侧组件。任何try添加更多组件的try都会导致异常。

放置分频器

MethodPurpose
void setDividerLocation(double)

void setDividerLocation(int)
int getDividerLocation()
设置或获取当前的分频器位置。设置分隔线位置时,可以将新位置指定为百分比(double)或像素位置(int)。
void resetToPreferredSizes()移动分隔器,以使两个组件的尺寸均处于首选尺寸。除非另有说明,否则这是拆分窗格在启动时进行自我划分的方式。
void setLastDividerLocation(int)
int getLastDividerLocation()
设置或获取分隔线的上一个位置。
int getMaximumDividerLocation()
int getMinimumDividerLocation()
获取分隔线的最小和最大位置。通过设置拆分窗格的两个组件的最小大小来隐式设置这些属性。
void setResizeWeight(float)
float getResizeWeight()
设置或获取拆分窗格的调整大小权重,该值介于 0.0(默认值)和 1.0 之间。有关调整大小权重的说明和示例,请参见放置分频器并限制其范围

使用分割窗格的示例

下表显示了一些使用JSplitPane的示例,并在其中描述了这些示例。

ExampleWhere DescribedNotes
SplitPaneDemo此页面和如何使用清单显示具有水平拆分的拆分窗格。
SplitPaneDividerDemoThis page演示如何使用组件尺寸信息和调整尺寸重量来放置分隔器。
SplitPaneDemo2This page将拆分窗格放在拆分窗格中以创建三向拆分。
TreeDemo如何使用树木使用垂直拆分的拆分窗格将树(在滚动窗格中)与编辑器窗格(在滚动窗格中)分开。不使用一键式扩展功能。
TextComponentDemoLiterals 组件功能使用垂直拆分的拆分窗格在滚动窗格中分离文本窗格和文本区域。
TextSamplerDemoLiterals 组件功能使用垂直拆分和调整大小权重为 0.5 的拆分窗格在滚动窗格中分隔文本窗格和编辑器窗格。拆分窗格位于具有相当复杂布局的容器的右半部分。使用诸如GridLayoutBorderLayout之类的布局 管理 器,以及拆分窗格的调整大小权重,以确保滚动窗格中的组件共享所有额外的空间。
ListSelectionDemo如何编写列表选择监听器使用垂直拆分的拆分窗格将包含列表和表的上部窗格(均在滚动窗格中)与下部窗格(包含滚动窗格上方的组合框)分开。下部窗格使用边框布局来使组合框保持较小,滚动窗格则贪婪地占用空间。