ScrollPane在Java Swing中无法滚动

huangapple go评论78阅读模式
英文:

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();
	}
}
英文:

I'm trying to adding the scrollpane in a inner panel,and the scrollbar is showing in the inner panel, but as i add the labels and textfield, the components were added but the scroll bar is not working.

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(&quot;New button&quot;);
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&lt;n;i++)
{
jlabel[i]=new JLabel(&quot;Label &quot;+(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

ScrollPane在Java Swing中无法滚动

This is the output image of my program.

答案1

得分: 1

你需要重新验证JScrollPane本身,以便重新布局其视口和视图,使其正常工作。但是您还需要设置内部JPanel的布局,以允许显示一个网格的内容,例如通过为其设置new GridLayout(0, 1)

例如:

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列的网格
    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);
        });
    }
}
英文:

You need to revalidate the JScrollPane itself for it to re-lay out its viewport and its view for this to work. But you will also need to set the layout of the inner JPanel to allow a grid of things to display for this to work right, such as by giving it a new GridLayout(0, 1) // one column, variable # of rows.

e.g.,

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.*;
@SuppressWarnings(&quot;serial&quot;)
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(&quot;New Row&quot;);
newRowBtn.addActionListener(e -&gt; {
int rows = (int) spinner.getValue();
for (int i = 0; i &lt; rows; i++) {
JLabel label = new JLabel(&quot;Label &quot; + String.format(&quot;%02d&quot;, 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(() -&gt; {
JFrame frame = new JFrame(&quot;GUI&quot;);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
AddNewProject2 project2 = new AddNewProject2();
frame.add(project2);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}

答案2

得分: 1

问题在于您在各处都使用了空布局(null layouts)。滚动条只会在添加到视口(viewport)的组件的首选大小(preferred size)大于视口的大小时才会出现。首选大小只有在使用布局管理器时才会动态计算。因此,解决方案是使用布局管理器。

对于对您的代码进行最基本的更改,您需要:

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

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

首先为顶部创建一个面板(panel):

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

然后将滚动窗格(scroll pane)添加到框架(frame):

add(scrollPane, BorderLayout.CENTER);

现在您需要使用:

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

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

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

如果您想要垂直添加组件,那么您需要在 "panel_1" 上使用不同的布局管理器。

阅读 Swing 教程中关于布局管理器的部分,获取更多信息和示例。

英文:

The problem is your usage of null layouts everywhere. The scrollbars only appear when the preferred size of a component added to the viewport is greater than the size of the viewport. The preferred size is only calculated dynamically when layout managers are used. So the solution is to use layout managers.

For the most basic changes to your code you are:

  1. remove all the setBounds() statements
  2. remove all the setLayout(null) statements

Then you can start using layout managers.

Start by creating a panel for the top:

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

Then add your scroll pane to the frame:

add(scrollPane, BorderLayout.CENTER);

Now you need to use:

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

The revalidate() invokes the layout manager so the new preferred size can be calculated.

In your example the horizontal scrollbar will appear because by default a JPanel uses a FlowLayout which displays components on a single line.

If you want the components added vertically then you will need to use a different layout manager on "panel_1".

Read the section from the Swing tutorial on Layout Managers for more information and examples.

huangapple
  • 本文由 发表于 2020年9月5日 23:01:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/63755323.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定