JScrollPane не прокручивается, когда я рисую JPanel в его ViewPort - PullRequest
0 голосов
/ 18 декабря 2018

Я пытаюсь нарисовать некоторые древовидные структуры на подклассе JPanel, который является клиентом (представление ViewPort) JScrollPane.Я могу нарисовать дерево очень хорошо, но даже если оно больше, чем область просмотра, JScrollPane не прокручивается.Идентичный JScrollPane, клиентом которого является JTextArea, работает нормально.

Приведенный ниже код создает кадр с двумя полосами прокрутки рядом - одна работает, а другая - нет.(Я просто рисую текст для простоты.) Я новичок в графическом интерфейсе Swing, поэтому я, несомненно, делаю глупости, но дни поиска и чтения не показали мне моей ошибки.

import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import java.awt.Graphics;

public class ScrollTest extends javax.swing.JFrame {

    public ScrollTest() {
        initComponents();
        prepComponents();
    }

    void prepComponents() {
        leftScrollPaneContent = new JTextArea();
        leftScrollPane.setViewportView(leftScrollPaneContent);
        rightScrollPaneContent = new TestPanel();
        rightScrollPane.setViewportView(rightScrollPaneContent);
        String s = "Test of JTextArea setText()\n\n";
        for (int i = 1; i < 30; i++) {
            s += "Line " + i + ": This is a test.\n";
        }
        leftScrollPaneContent.setText(s);
        rightScrollPaneContent.repaint();
    }

    @SuppressWarnings("unchecked")
    private void initComponents() {
        leftPanel = new javax.swing.JPanel();
        jPanelLabel = new javax.swing.JLabel();
        leftScrollPane = new javax.swing.JScrollPane();
        rightPanel = new javax.swing.JPanel();
        subclassLabel = new javax.swing.JLabel();
        rightScrollPane = new javax.swing.JScrollPane();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jPanelLabel.setText("JTextArea in a ScrollPane");

        leftScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
        leftScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

        javax.swing.GroupLayout leftPanelLayout = new javax.swing.GroupLayout(leftPanel);
        leftPanel.setLayout(leftPanelLayout);
        leftPanelLayout.setHorizontalGroup(
                leftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(leftPanelLayout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(leftScrollPane)
                        .addContainerGap())
                .addGroup(leftPanelLayout.createSequentialGroup()
                        .addGap(101, 101, 101)
                        .addComponent(jPanelLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 180, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap(114, Short.MAX_VALUE))
        );
        leftPanelLayout.setVerticalGroup(
                leftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(leftPanelLayout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jPanelLabel)
                        .addGap(18, 18, 18)
                        .addComponent(leftScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 332, Short.MAX_VALUE)
                        .addContainerGap())
        );

        subclassLabel.setText("JPanel subclass in a ScrollPane");

        rightScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
        rightScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

        javax.swing.GroupLayout rightPanelLayout = new javax.swing.GroupLayout(rightPanel);
        rightPanel.setLayout(rightPanelLayout);
        rightPanelLayout.setHorizontalGroup(
                rightPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(rightPanelLayout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(rightScrollPane)
                        .addContainerGap())
                .addGroup(rightPanelLayout.createSequentialGroup()
                        .addGap(66, 66, 66)
                        .addComponent(subclassLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 200, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap(77, Short.MAX_VALUE))
        );
        rightPanelLayout.setVerticalGroup(
                rightPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(rightPanelLayout.createSequentialGroup()
                        .addComponent(subclassLabel)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(rightScrollPane)
                        .addContainerGap())
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(leftPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(rightPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap(14, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addGroup(layout.createSequentialGroup()
                                        .addContainerGap()
                                        .addComponent(leftPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                                .addGroup(layout.createSequentialGroup()
                                        .addGap(17, 17, 17)
                                        .addComponent(rightPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                        .addContainerGap())
        );

        pack();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new ScrollTest().setVisible(true);
            }
        });
    }

    private javax.swing.JLabel jPanelLabel;
    private javax.swing.JPanel leftPanel;
    private javax.swing.JScrollPane leftScrollPane;
    private javax.swing.JPanel rightPanel;
    private javax.swing.JScrollPane rightScrollPane;
    private javax.swing.JLabel subclassLabel;
    // End of variables declaration                   
    private JTextArea leftScrollPaneContent;
    private JPanel rightScrollPaneContent;

    public class TestPanel extends JPanel {

        public void paint(Graphics g) {
            super.paint(g);
            g.drawString("Test of JPanel g.drawString()\n", 10, 20);
            for (int i = 3; i < 33; i++) {
                g.drawString("Line " + (i-2) + ": This is a test.", 10, 20 * i);
            }
        }
    }
}

1 Ответ

0 голосов
/ 18 декабря 2018

Ваш JTextArea leftScrollPaneContent переопределяет getPreferredSize(), который возвращает размер, умно полученный из фактического текста и шрифта.Окружающий JScrollPane использует этот размер, чтобы решить, нужны ли полосы прокрутки.
Кроме того, JTextArea (поскольку расширение от JTextComponent) также реализует интерфейс Scrollable.Это дает некоторые дополнительные подсказки окружающим JScollPane для лучшей прокрутки.


Ваш TestPanel rightScrollPaneContent ничего не делает.Поэтому он наследует метод getPreferredSize() от JPanel, возвращая лишь крошечный размер 10x10 (что имело бы смысл для пустого JPanel без дочерних компонентов).Поэтому окружающие JScrollPane решают, что нет необходимости показывать полосы прокрутки для этого якобы крошечного контента.

Следовательно, самое главное, в вашем TestPanel вам необходимо переопределить getPreferredSize() и вернуть разумныйБольшой размер там.В качестве бонуса (для лучшей прокрутки) вы также можете реализовать интерфейс Scrollable.Или вы решили расширить свой класс от другого класса, который уже реализует интерфейс Scrollable.

...