允许嵌套的JSplitPanes控制父JSplitPanes

Dan*_*Dan 6 java swing jsplitpane

下面是使用多个嵌套创建的简单布局的代码JSplitPanes.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSplitPane;

public class CDBurner extends JFrame {
    private static final long serialVersionUID = -6027473114929970648L;
    JSplitPane main, folder, rest;
    JPanel centeral, folders, favourites, tasks;
    JLabel label;

    private CDBurner() {
        super("Dan's CD Burner");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new GridLayout(1, 1));
        getContentPane().setBackground(Color.black);

        createLayout();

        pack();
        setMinimumSize(getSize());
        setExtendedState(getExtendedState() | JFrame.MAXIMIZED_BOTH);
        setVisible(true);
        requestFocus();
    }

    private void createLayout() {
        createPanels();
        rest = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, centeral, tasks);
        rest.setResizeWeight(1);
        rest.setContinuousLayout(true);
        rest.setOneTouchExpandable(true);
        folder = new JSplitPane(JSplitPane.VERTICAL_SPLIT, favourites, folders);
        folder.setResizeWeight(0.35);
        folder.setContinuousLayout(true);
        folder.setOneTouchExpandable(true);
        main = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, folder, rest);
        main.setResizeWeight(0);
        main.setContinuousLayout(true);
        main.setOneTouchExpandable(true);
        getContentPane().add(main);
    }

    private void createPanels() {
        createFolders();
        createCenter();
        createTaskSpool();
        createFavourites();
    }

    private void createFolders() {
        folders = new JPanel(new GridLayout(1, 1));
        label = new JLabel("Folder");
        folders.setMinimumSize(new Dimension(300, 100));
        folders.add(label);
    }

    private void createCenter() {
        centeral = new JPanel(new GridLayout(1, 1));
        label = new JLabel("Central");
        centeral.add(label);
        centeral.setMinimumSize(new Dimension(300, 100));
    }

    private void createTaskSpool() {
        tasks = new JPanel(new GridLayout(1, 1));
        label = new JLabel("Task");
        tasks.setMinimumSize(new Dimension(300, 100));
        tasks.add(label);
    }

    private void createFavourites() {
        favourites = new JPanel(new GridLayout(1, 1));
        label = new JLabel("Fav");
        favourites.setMinimumSize(new Dimension(300, 100));
        favourites.add(label);
    }

    public static void main(String[] args) {
        new CDBurner();
    }
}
Run Code Online (Sandbox Code Playgroud)

由于线rest.setResizeWeight(1);您可以拖动main (JSplitPane)分隔到右边,它会收缩tasks JPanel到直到两种JPanelsrest是最小尺寸.但是,如果你试图做相反的事情就没有发生.请参阅下面的图片以查看问题.

如果gui看起来像这样,你可以拖动main分隔线.

在此输入图像描述

你会得到这个结果.

在此输入图像描述

但是,如果它看起来像这样,你试图拖动rest分频器没有任何反应.

在此输入图像描述

这是因为它们的两侧rest JSplitPane已经处于最小尺寸.

问题
我怎样才能使它在拖动rest分隔线时影响它,main JSplitPane以便上面图像中显示的操作都可以?

Arc*_*ord 2

据我所知,您所描述的行为是意见分歧的正常行为。查看 Eclipse 等专业应用程序的分隔符的行为方式。

无论如何,我通过以编程方式控制休息分隔器的运动,为您所需的行为创建了一个解决方法JSplitPaneJSplitPane您只需在方法中创建休息后添加这些代码行即可createLayout()

SplitPaneUI spui = rest.getUI();
if (spui instanceof BasicSplitPaneUI) {           
    ((BasicSplitPaneUI) spui).getDivider().addMouseMotionListener(new MouseAdapter(){         
        @Override
        public void mouseDragged(MouseEvent E){
            int newPos = E.getPoint().x;                    
            if(newPos < 0 && folder.getSize().width > 300 && centeral.getSize().width <= 300){
                main.setDividerLocation(main.getDividerLocation() + newPos);
                validate();                     
            }
            if(centeral.getSize().width > 300 && tasks.getSize().width > 300){
                rest.setDividerLocation(rest.getDividerLocation() + newPos);
                validate(); 
            }
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

解释:
在第一行中,我们获取分隔线的 UI 对象并向其JSplitPane添加自定义MouseMotionListener。我们需要 UI 对象,因为真实对象JSplitPane不会直接获取任何鼠标事件。
在侦听器内,我们重写该mouseDragged方法并接收鼠标拖动分隔线时的实际 X 位置。
如果它是负值,我们将分隔线拖动到左侧。在这种情况下,如果中心面板已经缩小到最小尺寸 300 并且左侧文件夹面板仍然大于其最小尺寸,我们还希望主分隔线移动。
如果中央和右侧的任务面板仍然大于其最小尺寸 300,则其余分隔板应该是可移动的。