1

私は、ユーザーがエディター ウィンドウを縦または横に何度でも (つまり、任意の数のペインに) 自由に分割できるテキスト エディターで作業しています。1 つのウィンドウを縦にも横にも分割できます (たとえば、2 行、3 列を含むウィンドウなど)。各ペインには、JScrollPane 内に JTextArea とステータス バーが含まれています。

これまでの私のアプローチは、ネストされた JSplitPanes を使用することでした。ウィンドウ内のスペースが、垂直または水平に分割されたすべてのペイン間で均等に分割されるように、分割ペインの仕切りを配置するのに苦労しました。私はそれを正しくすることにかなり近づいてきましたが、多くの場所で setPreferredSize() を使用する必要がありました ( Java Swing で set[Preferred|Maximum|Minimum]Size メソッドの使用を避けるべきですか? ) .

完全に別のアプローチを取る方が簡単/良いかどうか疑問に思っています。MultiSplitPaneは魅力的に見えます...

私の状況に最適なレイアウト/アプローチは何ですか?

4

2 に答える 2

1

MultiSplitPane レイアウトの学習に時間を費やすことにしました。それは良い解決策のように見えます。

テストとして書いたコードがこちら。これは基本的に、ユーザーがさまざまな方法でウィンドウを分割すると動的に変化するレイアウトのシミュレーションです。少し長くなりますが、MultiSplitPane を学習しようとしている人にとっては役立つかもしれません。

最終結果は次のようになります。

ここに画像の説明を入力

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.util.LinkedList;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import org.jdesktop.swingx.MultiSplitPane;
import org.jdesktop.swingx.MultiSplitLayout.*;

@SuppressWarnings("serial")
class MultiSplitPaneTest extends JFrame {
    private final static String sampleText;

    static {
        String text = "I'm working on a text editor in which the user is free to divide the editor window vertically or horizontally any number of times (ie, into any number of panes).\n";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            sb.append(text);
        }
        sampleText = sb.toString();
    }

    private class MyScrollPane extends JScrollPane {
        public MyScrollPane(final Component view) {
            super(view);
        }
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(1440, 900);
        }
    }

    public MultiSplitPaneTest() {
        // The application opens with a window containing a single pane (a single text area).

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Container cp = getContentPane();
        cp.setLayout(new BorderLayout());

        JTextArea ta1 = new JTextArea();
        ta1.setText("TEXT AREA 1\n" + sampleText);

        MyScrollPane sp1 = new MyScrollPane(ta1);
        sp1.setViewportView(ta1);

        cp.add(sp1, BorderLayout.CENTER);

        pack();
        setLocationRelativeTo(null);
        setVisible(true);

        // -------------------------------------------------

        // Let's say the user splits the window horizontally, creating a second pane.
        // We'll simulate that with the following code.

        JTextArea ta2 = new JTextArea();
        ta2.setText("TEXT AREA 2\n" + sampleText);

        MyScrollPane sp2 = new MyScrollPane(ta2);
        sp2.setViewportView(ta2);

        Leaf leaf1 = new Leaf("1");
        Leaf leaf2 = new Leaf("2");

        LinkedList<Node> rootChildren = new LinkedList<>();
        rootChildren.add(leaf1);
        rootChildren.add(new Divider());
        rootChildren.add(leaf2);

        Split root = new Split();
        root.setRowLayout(true);
        root.setChildren(rootChildren);

        MultiSplitPane multiSplitPane = new MultiSplitPane();
        multiSplitPane.getMultiSplitLayout().setModel(root);

        multiSplitPane.add(sp1, "1");
        multiSplitPane.add(sp2, "2");

        cp.remove(sp1);
        cp.add(multiSplitPane, BorderLayout.CENTER);

        // --------------------------------------------------

        // Let's say the user splits the window horizontally again, creating a new pane on the very left.

        JTextArea ta3 = new JTextArea();
        ta3.setText("TEXT AREA 3\n" + sampleText);

        MyScrollPane sp3 = new MyScrollPane(ta3);
        sp3.setViewportView(ta3);

        Leaf leaf3 = new Leaf("3");

        rootChildren.add(0, leaf3);
        rootChildren.add(1, new Divider());

        root.setChildren(rootChildren);

        multiSplitPane.add(sp3, "3");

        multiSplitPane.revalidate();

        // --------------------------------------------------

        // Let's say the user decides to remove the center pane (that is, the first pane that we started with).

        rootChildren.remove(2); // Remove leaf1.
        rootChildren.remove(2); // Remove the divider following leaf1.

        root.setChildren(rootChildren);

        multiSplitPane.remove(sp1);

        multiSplitPane.revalidate();

        // --------------------------------------------------

        // Let's say the user creates another pane, this time splitting the pane on the right vertically.

        rootChildren.remove(leaf2);

        JTextArea ta4 = new JTextArea();
        ta4.setText("TEXT AREA 4\n" + sampleText);

        MyScrollPane sp4 = new MyScrollPane(ta4);
        sp4.setViewportView(ta4);

        Leaf leaf4 = new Leaf("4");

        LinkedList<Node> branchChildren = new LinkedList<>();
        branchChildren.add(leaf2);
        branchChildren.add(new Divider());
        branchChildren.add(leaf4);

        Split branch = new Split();
        branch.setRowLayout(false);
        branch.setChildren(branchChildren);

        rootChildren.add(branch);

        root.setChildren(rootChildren);

        multiSplitPane.add(sp4, "4");

        multiSplitPane.revalidate();
    }
}
于 2012-10-14T03:21:37.363 に答える
1

今、私はあなたが望むものについていくつかの仮定をしています. すべて同じ幅/高さのテキスト ペインを動的に追加する簡単な方法があるかどうかを尋ねていると思います (垂直または水平に分割しますが、2 つを混在させません)。

水平分割の例

スクリーンショットの水平分割

縦割りの例

スクリーンショットの垂直分割

その場合は、BoxLayout を使用することをお勧めします。これは、ほとんど構成を行わなくても実行できます。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class SplitablePanel extends Box{

    Box container;
    Dimension minSize = new Dimension(400, 300);

    public SplitablePanel(int axis){
        super(BoxLayout.Y_AXIS);

        //Container that holds all the text areas
        container = new Box(axis);
        container.setAlignmentX(Box.LEFT_ALIGNMENT);
        add(container);

        JTextArea text = new JTextArea();
        container.add(new JScrollPane(text));

        //Button to add another pane
        JButton split = new JButton("Split");
        split.setAlignmentX(Box.LEFT_ALIGNMENT);
        split.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e) {
                JTextArea text = new JTextArea();
                container.add(new JScrollPane(text));
                revalidate();
            }});
        add(split);

        //Button To switch Axis - more for demo purposes
        JButton axisChanger = new JButton("Change Axis");
        axisChanger.setAlignmentX(Box.LEFT_ALIGNMENT);
        axisChanger.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Box newContainer;
                if(((BoxLayout)container.getLayout()).getAxis() == BoxLayout.X_AXIS){
                    newContainer = Box.createVerticalBox();
                } else{
                    newContainer = Box.createHorizontalBox();
                }

                for(Component c : container.getComponents()){
                    container.remove(c);
                    newContainer.add(c);
                }
                remove(container);
                add(newContainer, 0);
                container = newContainer;
                container.setAlignmentX(Box.LEFT_ALIGNMENT);
                revalidate();
            }
        });
        add(axisChanger);

    }

    @Override
    public Dimension getPreferredSize() {
        Dimension result = super.getPreferredSize();
        result.width = result.width > minSize.width ? result.width : minSize.width;
        result.height = result.height > minSize.height ? result.height : minSize.height;
        return result;
    }

    public static void main(String[] args) {
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new SplitablePanel(BoxLayout.X_AXIS));
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

}
于 2012-10-12T19:55:25.853 に答える