ScrollPane 在 Java Swing 中不滚动

ScrollPane not Scrolling in 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, 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();
    }
}

上述程序的输出

这是我程序的输出图像。

您需要重新验证 JScrollPane 本身,才能 re-lay 显示其视口和视图,才能正常工作。但是您还需要设置内部 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, 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, 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);
        });
    }
}

问题是您到处都使用空布局。只有当添加到视口的组件的首选大小大于视口大小时,滚动条才会出现。首选大小仅在使用布局管理器时动态计算。所以解决方案是使用布局管理器。

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

  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 教程部分以获取更多信息和示例。