java - 当我在 ViewPort 中绘制 JPanel 时,JScrollPane 不滚动

标签 java swing jscrollpane

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

下面的代码创建了一个框架,其中有 2 个并排的滚动 Pane - 一个可以工作,另一个则不能。 (为了简单起见,我只是绘制文本。)我是 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);
            }
        }
    }
}

最佳答案

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

<小时/>

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

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

关于java - 当我在 ViewPort 中绘制 JPanel 时,JScrollPane 不滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53823324/

相关文章:

java - 为什么我的 setLocation(x,y) 不起作用?

java - 行条目少于显示和排序问题的 JTable

java - JTextArea 的 JScrollPane 不起作用;不会滚动

javascript - Select2 + 自定义滚动条

java : return multiple values from a method

java - JTextArea 在 actionListener 之前填充

java - Swing:如果主窗口关闭,如何杀死工作线程?

javascript - 如何使 child 的 div 宽度与其内容与 parent 的 div 宽度相匹配 100% overflow-x : auto in IE & FF

java - Scene Builder 2.0 未启动

java - WebDriver - 无法找到元素