Почему моя JPanel внутри JScrollPane не прокручивается? - PullRequest
8 голосов
/ 08 февраля 2012

У меня есть JPanel (желтый), помещенный в JScrollPane.

pic1

При вводе текста в JTextPane он изменяется, но вертикальная полоса прокрутки по-прежнему не активна. yelowPanel.getSize() возвращает то же значение, которое было раньше. (Вы можете увидеть это на redPanel).

pic2

Так как я могу обновить yellowPanel? Я хочу прокрутить панель по вертикали. Я пытался:

panelCreating.revalidate();
panelCreating.invalidate();
panelCreating.repaint();

Работает только panelCreating.setPreferredSize(new Dimension(333, 777));, но я не знаю, какой размер установить. Это зависит от содержания.

Вот небольшой пример:

package swingtest;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;

public class SwingTest extends JFrame {

    public SwingTest() {
        initComponents();
    }

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

            @Override
            public void run() {
                new SwingTest().setVisible(true);
            }
        });
    }
    private JPanel panelCenter, panelCreating;
    private JScrollPane scrollPaneCreating, scrollPaneCenter;
    private JTextPane textPane1, textPane2;
    private JButton button1;

    private void initComponents() {
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setMinimumSize(new Dimension(300, 300));

        panelCreating = new JPanel();
        panelCreating.setMinimumSize(new Dimension(160, 200));
        panelCreating.setPreferredSize(new Dimension(160, 200));
        scrollPaneCreating = new JScrollPane(panelCreating,
            JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
            JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

        textPane1 = new JTextPane();
        textPane1.setText("a\na");
        textPane2 = new JTextPane();
        textPane2.setText("b\nb");
        button1 = new JButton("+++");

        panelCenter = new JPanel();
        panelCenter.setBackground(Color.blue);
        scrollPaneCenter = new JScrollPane(panelCenter);



        // ----------------- Left Panel Init -----------------------

        panelCreating.setLayout(new GridBagLayout());
        panelCreating.setBackground(Color.ORANGE);
        panelCreating.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));

        GridBagConstraints c = new GridBagConstraints();
        c.insets = new Insets(0, 0, 4, 4);
        c.anchor = GridBagConstraints.FIRST_LINE_START;
        c.weightx = c.weighty = 0;

        c.gridx = 0;
        c.gridy = GridBagConstraints.RELATIVE;
        c.gridwidth = GridBagConstraints.REMAINDER;
        c.gridheight = 1;
        c.fill = GridBagConstraints.BOTH;
        panelCreating.add(textPane1, c);

        button1.addActionListener(new ActionListener() {

            int height = 50;

            @Override
            public void actionPerformed(ActionEvent e) {
                textPane1.setText(textPane1.getText() + "\na");
                textPane1.setPreferredSize(new Dimension(150, height));
                textPane2.setText(textPane2.getText() + "\nb");
                textPane2.setPreferredSize(new Dimension(150, height));
                height += 30;

                panelCreating.revalidate();
                panelCreating.repaint();
                scrollPaneCreating.revalidate();
            }
        });
        panelCreating.add(button1, c);

        panelCreating.add(textPane2, c);

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

        getContentPane().setLayout(new GridBagLayout());
        c = new GridBagConstraints();

        c.ipadx = c.ipady = 0;
        c.insets = new Insets(0, 0, 0, 0);
        c.weighty = 0;
        c.gridheight = 1;
        c.gridx = 0;
        c.gridy = 1;
        c.gridwidth = 1;
        c.weightx = 0;
        c.fill = GridBagConstraints.BOTH;
        getContentPane().add(scrollPaneCreating, c);


        c.gridx = 1;
        c.gridy = 1;
        c.fill = GridBagConstraints.BOTH;
        c.weightx = 1;
        c.weighty = 1;
        getContentPane().add(scrollPaneCenter, c);

    }
}

Желтая панель также использует GridBagLayout. Извините за мой английский

Ответы [ 3 ]

6 голосов
/ 08 февраля 2012

Вместо установки предпочтительного размера на panelCreating, установите его на scrollPaneCreating.И не устанавливайте предпочтительный размер текстовых компонентов, они будут расти по мере добавления к ним новых строк текста.Идея состоит в том, чтобы панель внутри панели прокрутки становилась настолько большой, насколько это необходимо, и просто ограничивала размер самой панели прокрутки.

    // [...]

    panelCreating = new JPanel();
    //panelCreating.setMinimumSize(new Dimension(160, 200));
    //panelCreating.setPreferredSize(new Dimension(160, 200));
    scrollPaneCreating = new JScrollPane(panelCreating,
        JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
        JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    scrollPaneCreating.setMinimumSize(new Dimension(160, 200));
    scrollPaneCreating.setPreferredSize(new Dimension(160, 200));

    // [...]

        @Override
        public void actionPerformed(ActionEvent e) {
            textPane1.setText(textPane1.getText() + "\na");
            //textPane1.setPreferredSize(new Dimension(150, height));
            textPane2.setText(textPane2.getText() + "\nb");
            //textPane2.setPreferredSize(new Dimension(150, height));
            //height += 30;

            // This isn't necessary either
            //panelCreating.revalidate();
            //panelCreating.repaint();
            //scrollPaneCreating.revalidate();
        }

Отредактировано, чтобы добавить: другой альтернативой являетсяустановите размеры на JViewport, который прикреплен к панели прокрутки.В окне просмотра отображается содержимое.Вы можете рассматривать панель прокрутки как состоящую из области просмотра и полос прокрутки.Если для области прокрутки задан фиксированный размер, то размер области просмотра определяется путем вычитания размера полосы прокрутки.Но если для окна просмотра установлен фиксированный размер, то размер области прокрутки определяется путем добавления размера полосы прокрутки к размеру окна просмотра.Установка фиксированного размера в окне просмотра предпочтительнее, если вы хотите точно контролировать объем содержимого, отображаемого на экране, поскольку размеры полосы прокрутки могут различаться в зависимости от операционной системы.

scrollPaneCreating.getViewport().setMinimumSize(new Dimension(160, 200));
scrollPaneCreating.getViewport().setPreferredSize(new Dimension(160, 200));
4 голосов
/ 08 февраля 2012

По умолчанию макет JPanel равен FlowLayout. Попробуйте GridLayout вместо этого. Здесь есть связанный пример здесь . Например,

panelCreating = new JPanel(new GridLayout());
scrollPaneCreating = new JScrollPane(panelCreating);

Приложение: также рассмотрите вложенные макеты. В приведенном ниже примере для левой панели используется BoxLayout.

enter image description here

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;

/** @see https://stackoverflow.com/questions/9184476 */
public class SwingTest extends JFrame {

    private static final int N = 8;

    public SwingTest() {
        initComponents();
    }

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

            @Override
            public void run() {
                new SwingTest().setVisible(true);
            }
        });
    }
    private JPanel panelCenter, panelCreating;
    private JScrollPane scrollPaneCreating, scrollPaneCenter;

    private void initComponents() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        panelCreating = new JPanel();
        scrollPaneCreating = new JScrollPane(panelCreating,
            JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
            JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

        panelCenter = new JPanel();
        panelCenter.setBackground(Color.blue);
        scrollPaneCenter = new JScrollPane(panelCenter);

        // ----------------- Left Panel Init -----------------------
        panelCreating.setLayout(new BoxLayout(panelCreating, BoxLayout.Y_AXIS));
        panelCreating.setBackground(Color.orange);
        panelCreating.setBorder(BorderFactory.createEmptyBorder(N, N, N, N));

        panelCreating.add(createTextPane());
        panelCreating.add(Box.createVerticalStrut(N));
        panelCreating.add(createTextPane());
        panelCreating.add(Box.createVerticalStrut(N));
        panelCreating.add(createTextPane());

        // -------------------------------------------------------
        setLayout(new GridLayout(1, 0));
        add(scrollPaneCreating);
        add(scrollPaneCenter);
        pack();
    }

    private JTextPane createTextPane() {
        JTextPane pane = new JTextPane();
        pane.setText(""
            + "Twas brillig and the slithy toves\n"
            + "Did gyre and gimble in the wabe;\n"
            + "All mimsy were the borogoves,\n"
            + "And the mome raths outgrabe.");

        pane.setBorder(BorderFactory.createEmptyBorder(N, N, N, N));
        return pane;
    }
}
0 голосов
/ 05 мая 2013

Я исправил вашу проблему, добавив 1 строку.

panelCreating.setPreferredSize(new Dimension((int) panelCreating.getPreferredSize().getWidth(),
                    (int)(panelCreating.getPreferredSize().getHeight()+30)));

Строка должна быть вставлена ​​после следующих строк:

@Override
        public void actionPerformed(ActionEvent e) {
            textPane1.setText(textPane1.getText() + "\na");
            textPane1.setPreferredSize(new Dimension(150, height));
            textPane2.setText(textPane2.getText() + "\nb");
            textPane2.setPreferredSize(new Dimension(150, height));
            height += 30;

Объяснение: Компоновка мешка с сеткой не устанавливает свою панельпредпочтительный размер, когда вы устанавливаете предпочтительный размер textPanes внутри него, но scrollPane прокручивается только на основе предпочтительного размера панели в нем.Таким образом, вы должны устанавливать новый предпочтительный размер панели каждый раз, когда вы меняете размер компонентов в ней, тогда scrollPane будет точно знать, что он должен делать.Это то, что я сделал, добавив строку, которая увеличила предпочтительный размер createPanel, которая внутри scrollPanel

...