Изменение размера с холстом в jscrollpane в jsplitpane

Я создаю приложение, используя редактор графического интерфейса NetBeans, в котором я хочу иметь JSplitPane, верхний компонент которого будет Canvas в пределах JScrollPane, а нижний компонент будет JTextArea, или что-то в этом роде.

Когда я вытаскиваю делитель вниз и, таким образом увеличивая размер верхнего компонента, все, кажется, очень просто изменяет размер.

Проблема возникает, когда я пытаюсь продвинуть разделитель вверх: Похоже, что разделитель находится ниже Canvas (и, возможно, ниже JScrollPane).

Я пробовал различные комбинации предпочтительных/минимальных/максимальных размеров JScrollPane и Canvas, но ничего не работает.

Это часть кода, сгенерированного Netbeans, который может иметь какое-то отношение к проблеме:

jSplitPane1 = new javax.swing.JSplitPane();
jScrollPane1 = new javax.swing.JScrollPane();
canvas1 = new java.awt.Canvas();
jTextField1 = new javax.swing.JTextField();

jSplitPane1.setDividerLocation(300);
jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);

jScrollPane1.setViewportView(canvas1);

jSplitPane1.setTopComponent(jScrollPane1);

jTextField1.setText("jTextField1");
jSplitPane1.setRightComponent(jTextField1);

Поскольку это мой первый вопрос, мне не разрешено вставлять изображение в вопрос, поэтому я просто отправлю ссылку:

Красные стрелки указывают положение разделителя.

Заранее благодарим за ваше время.

Ответ 1

Прочитав комментарий от davidbuzatto, я разобрался в смешении компонентов AWT и Swing, и мне было немного неожиданно узнать, что это такая плохая практика.

Я нашел наиболее точный ответ на мой вопрос здесь

Тяжелые компоненты имеют собственный Z-порядок. Именно по этой причине Swing и AWT нельзя комбинировать в одном контейнере. Если они есть, компоненты AWT будут нарисованы поверх компонентов Swing.

Например: Когда AWT-компоненты используются с JtabbedPane, они не исчезают при переключении вкладок.

Спасибо davidbuzatto за то, что показал мне способ: -)

Ответ 2

Вместо setPreferredSize() пусть ваши компоненты вычислит свой собственный предпочтительный размер и pack() прилагаемый Window для размещения. В приведенном ниже примере добавляется экземпляр draw.GraphPanel вверху и соответствующая панель управления снизу.

image

import draw.GraphPanel;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;

/**
 * @see https://stackoverflow.com/q/11942961/230513
 */
public class SplitGraph extends JPanel {

    public SplitGraph() {
        super(new GridLayout());
        JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
        GraphPanel graphPanel = new GraphPanel();
        split.setTopComponent(new JScrollPane(graphPanel));
        split.setBottomComponent(graphPanel.getControlPanel());
        this.add(split);
    }

    private void display() {
        JFrame f = new JFrame("SplitGraph");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new SplitGraph().display();
            }
        });
    }
}

Ответ 3

Как я уже сказал в своих комментариях, вы не должны смешивать компоненты AWT и Swing. Я думаю, что вы не используете компоненты правильно. Взгляните, это простой пример использования JSplitPane.

import java.awt.*; // it is necessary to use the Dimension and BorderLayout classes
import javax.swing.*;

public class Foo extends JFrame {

    public Foo() {

        setTitle( "Splits" );
        setDefaultCloseOperation( EXIT_ON_CLOSE );
        setSize( 400, 400 );

        JSplitPane split = new JSplitPane( JSplitPane.VERTICAL_SPLIT );
        split.setDividerLocation( 200 );
        add( split );

        JPanel panel1 = new JPanel();
        panel1.setLayout( new BorderLayout() );
        panel1.add( new JLabel( "top panel" ), BorderLayout.NORTH );

        JPanel myDrawPanel = new JPanel();
        myDrawPanel.setPreferredSize( new Dimension( 100, 100 ) );
        myDrawPanel.add( new JLabel( "draw panel here!" ) );
        panel1.add( new JScrollPane( myDrawPanel ), BorderLayout.CENTER );

        split.setTopComponent( panel1 );


        JPanel panel2 = new JPanel();
        panel2.add( new JLabel( "bottom panel" ) );
        split.setBottomComponent( panel2 );


        setVisible( true );

    }

    public static void main( String[] args ) {
        new Foo();
    }

}