ScrollPane无法在Java Swing中滚动

问题描述

我试图在内部面板中添加滚动窗格,并且内部面板中显示滚动条,但是当我添加标签和文本字段时,添加了组件,但是滚动条不起作用。

public class AddNewProject extends JFrame {
    private JButton btnNewButton;
    private JSpinner spinner;
    private JScrollPane scrollPane;
    private JPanel panel_1;
    
    public AddNewProject() {
        getContentPane().setLayout(null);
        
        JPanel panel = new JPanel();
        panel.setBackground(Color.PINK);
        panel.setBounds(134,37,583,610);
        getContentPane().add(panel);
        panel.setLayout(null);
        
        spinner = new JSpinner();
        spinner.setModel(new SpinnerNumberModel(0,30,1));
        spinner.setBounds(63,51,164,31);
        panel.add(spinner);
        
        btnNewButton = new JButton("New button");
        btnNewButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                int n=(int) spinner.getValue();
                JLabel jlabel[]=new JLabel[n];
                JTextField jtxt[]=new JTextField[n];
                                
                for(int i =0;i<n;i++)
                {
                    jlabel[i]=new JLabel("Label "+(i+1));
                    jtxt[i]=new JTextField(32);
                    
                    panel_1.add(jlabel[i]);
                    panel_1.add(jtxt[i]);
                }
                panel_1.validate();
                panel_1.repaint();
            }
        });
        btnNewButton.setBounds(336,54,149,28);
        panel.add(btnNewButton);
        
        scrollPane = new JScrollPane();     
        scrollPane.setBounds(69,141,434,298);
        panel.add(scrollPane);
        
        panel_1 = new JPanel();
        
        scrollPane.setViewportView(panel_1);
        scrollPane.setPreferredSize(new Dimension(434,300));
        scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
        scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        
        setSize(900,800);
        setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
        
    }
    public static void main(String[] args) {
        new AddNewProject();
    }
}

上述程序的输出

Output of the above Program

这是我程序的输出图像。

解决方法

您需要重新验证JScrollPane本身,才能重新布局其视口和其视图,以使其正常工作。但是,您还需要设置内部JPanel的布局,以允许显示网格以使其正常工作,例如通过给其new GridLayout(0,1) // one column,variable # of rows

例如

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.*;

@SuppressWarnings("serial")
public class AddNewProject2 extends JPanel {
    private JPanel gridPanel = new JPanel(new GridLayout(0,1)); // 1 column grid
    private JSpinner spinner = new JSpinner(new SpinnerNumberModel(0,30,1));
    
    
    public AddNewProject2() {
        JPanel wrapperPanel = new JPanel(new BorderLayout());
        wrapperPanel.add(gridPanel,BorderLayout.PAGE_START);
        JScrollPane scrollPane = new JScrollPane(wrapperPanel);
        scrollPane.getViewport().setPreferredSize(new Dimension(450,500));
        
        JButton newRowBtn = new JButton("New Row");
        newRowBtn.addActionListener(e -> {
            int rows = (int) spinner.getValue();
            for (int i = 0; i < rows; i++) {
                JLabel label = new JLabel("Label " + String.format("%02d",i + 1));
                JTextField txtFld = new JTextField(32);
                JPanel row = new JPanel();
                row.add(label);
                row.add(txtFld);
                gridPanel.add(row);
            }
            
            scrollPane.revalidate();
        });
        
        JPanel topPanel = new JPanel();
        topPanel.add(spinner);
        topPanel.add(newRowBtn);
        
        int gap = 20;
        setBorder(BorderFactory.createEmptyBorder(gap,gap,gap));
        setLayout(new BorderLayout(gap,gap));
        
        add(topPanel,BorderLayout.PAGE_START);
        add(scrollPane);
    }
    
    
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("GUI");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
            AddNewProject2 project2 = new AddNewProject2();
            frame.add(project2);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }
}
,

问题是您到处都使用null布局。仅当添加到视口的组件的首选大小大于视口的大小时,才会显示滚动条。首选大小仅在使用布局管理器时动态计算。因此解决方案是使用布局管理器。

对于代码的最基本更改,您是:

  1. 删除所有setBounds()语句
  2. 删除所有setLayout(null)语句

然后,您可以开始使用布局管理器。

首先从顶部创建一个面板:

JPanel topPanel = new JPanel();
topPanel.add(spinner)
topPanel.add(btnNewButton);
add(topPanel,BorderLayout.PAGE_START);

然后将滚动窗格添加到框架:

add(scrollPane,BorderLayout.CENTER);

现在您需要使用:

//panel_1.validate();
panel_1.revalidate();

revalidate()调用布局管理器,以便可以计算新的首选大小。

在您的示例中,将显示水平滚动条,因为默认情况下,JPanel使用FlowLayout,它在一行上显示组件。

如果要垂直添加组件,则需要在“ panel_1”上使用其他布局管理器。

阅读Layout Managers的Swing教程中的部分,以获取更多信息和示例。