CrossSplitPane

CrossSplitPaneTestでマウスにより分割

十字分割窓のひな形を作ってみました。
もうチョット丁寧に作らないとダメですが、基本的な動作はできてます。

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;

public class CrossSplitPaneTest  extends JPanel {
    public static final int DIVIDER_WIDTH = 5;  // 幅[dot]
    protected JComponent pane = new JComponent[2][2];   // 常に2x2
    protected int splitX;       // 分割バーの左の座標
    protected int splitY;       // 分割バーの上の座標
    public CrossSplitPaneTest() {
        setLayout(new JSpreadLayoutManager());
        splitX = 100;
        splitY = 100;
        CrossSplitListener mouselistener = new CrossSplitListener();
        addMouseListener(mouselistener);
        addMouseMotionListener(mouselistener);
    }
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Rectangle rect = getBounds();
        g.setColor(Color.BLUE);
        g.fillRect(0, 0, rect.width, rect.height);
    }
    public void setPane(int row, int col, JComponent comp) {
        if (pane[row][col] != null) remove(pane[row][col]);
        pane[row][col] = comp;
        add(comp);
    }
    
    public class JSpreadLayoutManager implements LayoutManager {
        JSpreadLayoutManager() {
        }
        /** 指定されたコンテナを配置します。 */
        public void layoutContainer(Container target) {
            synchronized (target.getTreeLock()) {
                // 一応インセットも対応しているのでボーダーが正しく使える。
                Insets insets = target.getInsets();
                int x0 = insets.left;
                int y0 = insets.top;
                int x9 = target.getWidth() - insets.right;
                int y9 = target.getHeight() - insets.bottom;
                int x1 = splitX;
                int y1 = splitY;
                int x2 = x1 + DIVIDER_WIDTH;
                int y2 = y1 + DIVIDER_WIDTH;
                pane[0][0].setBounds(x0, y0, x1-x0, y1-y0);
                pane[0][1].setBounds(x2, y0, x9-x2, y1-y0);
                pane[1][0].setBounds(x0, y2, x1-x0, y9-y2);
                pane[1][1].setBounds(x2, y2, x9-x2, y9-y2);
            }
        }
        public Dimension minimumLayoutSize(Container parent) {
            return new Dimension(0,0);  // 本当は個々のペインの最小サイズを加算すべき
        }
        public Dimension preferredLayoutSize(Container parent) {
            return new Dimension(200, 200); // 本当は個々のペインの推奨サイズを加算すべき
        }
        public void addLayoutComponent(String name, Component comp){}
        public void removeLayoutComponent(Component comp) {}
    }
    
    /**
     * マウスで分割位置を変えるリスナ.
     * 本当は中心以外は、縦横どちらかの移動にした方がいい。
     */
    class CrossSplitListener extends MouseInputAdapter {
        int last_x = 0;
        int last_y = 0;
        public void mousePressed(MouseEvent e) {
            System.out.println(e);
            last_x = e.getX();
            last_y = e.getY();
        }
        public void mouseReleased(MouseEvent e) {
            System.out.println("splitX="+splitX+" e.getX()="+e.getX()+" getX()="+getX());
            splitX = e.getX();  // 本当はもっと座標の範囲チェックなどをした方がよい
            splitY = e.getY();
            revalidate();
        }
        public void mouseDragged(MouseEvent e) {
            System.out.println(e);
            Graphics g = getParent().getGraphics();
            g.setXORMode(Color.WHITE);
            g.fillRect(last_x, 0, DIVIDER_WIDTH, getHeight());  // hide
            g.fillRect(0, last_y, getWidth(), DIVIDER_WIDTH);   // hide
            last_x = e.getX();
            last_y = e.getY();
            g.fillRect(last_x, 0, DIVIDER_WIDTH, getHeight());  // show
            g.fillRect(0, last_y, getWidth(), DIVIDER_WIDTH);   // show
        }
        public void mouseMoved(MouseEvent e) {
            setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
        }
        public void mouseClicked(MouseEvent e) {
            // 左ボタンでダブルクリックしたとき、分割を解除する。・・・とか
        }
    }
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        CrossSplitPaneTest divider = new CrossSplitPaneTest();
        divider.setPane(0, 0, new JTextArea("(0,0)のペインだよ"));
        divider.setPane(0, 1, new JTextArea("(0,1)のペインだよ"));
        divider.setPane(1, 0, new JTextArea("(1,0)のペインだよ"));
        divider.setPane(1, 1, new JTextArea("(1,1)のペインだよ"));
        //divider.setBorder(new TitledBorder("ぼーだー"));
        frame.getContentPane().add(divider);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(640, 480);
        frame.setVisible(true);
    }
}