当我在JPanel的ViewPort中绘制JPanel时,JScrollPane无法滚动

时间:2018-12-17 21:36:43

标签: java swing jscrollpane

我正在尝试在JPanel的客户端(ViewPort视图)的JScrollPane子类上绘制一些树结构。我可以很好地绘制树,但是即使树大于视口,JScrollPane也不会滚动。客户端为JScrollPane的相同JTextArea可以正常工作。

下面的代码创建一个带有两个并排滚动窗格的框架-一个起作用,另一个不起作用。 (为了简单起见,我只是在绘制文本。)我是Swing GUI的新手,所以我无疑在做一些愚蠢的事情,但是几天的搜索和阅读并没有向我显示我的错误。

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 :(得分:1)

您的JTextArea leftScrollPaneContent覆盖 getPreferredSize()可巧妙地返回尺寸 从实际的文本和字体派生。 周围的JScrollPane使用此大小来确定 如果需要滚动条。
此外,JTextArea(因为从JTextComponent扩展而来) 还实现了Scrollable接口。 这为周围的JScollPane提供了一些额外的提示 以获得更好的滚动行为。


您的TestPanel rightScrollPaneContent不执行任何操作。 因此,它从getPreferredSize()继承了JPanel方法 仅返回一个很小的10x10尺寸(对于 空JPanel,没有子组件)。 因此,周围的JScrollPane决定不存在 需要显示任何据称是微小内容的滚动条。

因此,最重要的是,您需要在TestPanel中覆盖 getPreferredSize()并在其中返回合理的大尺寸。 作为奖励(为了更好的滚动行为),您还可以实施 Scrollable界面。 或者您选择从其他班级扩展班级 已经实现了Scrollable接口。