这就是我最初做的。
public class MyFrame extends JFrame {
public MyFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setPreferredSize(new Dimension(500 ,300));
setResizable(false);
pack();
setLocationRelativeTo(null);
initComponents();
}
private void initComponents() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
for (int i=0; i < 100; i++)
panel.add(new JLabel("some text"));
JScrollPane scrollPane = new JScrollPane(panel,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
// Here I create a JPanel to replace the contentPane of JFrame
JPanel contentPane = new JPanel();
contentPane.add(scrollPane);
setContentPane(contentPane);
}
如果我用这个代替最后3行:
getContentPane().add(scrollPane);
一切都好。但正如我之前所做的那样,垂直滚动条没有显示出来。是什么造成的?将JPanel设置为contentPane是错误的吗?
更新: 如果contentPane更改为BorderLayout,一切正常。
// Here I create a JPanel to replace the contentPane of JFrame
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.add(scrollPane);
setContentPane(contentPane);
所以问题是默认的FlowLayout?
解决: 问题是FlowLayout。它包装了JScrollPane并隐藏了工具栏。使用
scrollPane.setPreferredSize(new Dimension(500, 400)); // longer space in x-axis
解决它。
答案: 不应在使用FlowLayout的Container内使用JSrollPane。
答案 0 :(得分:2)
首先,将自己的组件用作内容窗格并没有什么不妥。但是默认内容窗格也是一个JPanel实例,因此实际上没有必要用您自己的面板替换它,除非您想使用非面板内容窗格或自定义面板组件。
这是默认内容窗格的样子:
/**
* Called by the constructor methods to create the default
* <code>contentPane</code>.
* By default this method creates a new <code>JComponent</code> add sets a
* <code>BorderLayout</code> as its <code>LayoutManager</code>.
* @return the default <code>contentPane</code>
*/
protected Container createContentPane() {
JComponent c = new JPanel();
c.setName(this.getName()+".contentPane");
c.setLayout(new BorderLayout() {
/* This BorderLayout subclass maps a null constraint to CENTER.
* Although the reference BorderLayout also does this, some VMs
* throw an IllegalArgumentException.
*/
public void addLayoutComponent(Component comp, Object constraints) {
if (constraints == null) {
constraints = BorderLayout.CENTER;
}
super.addLayoutComponent(comp, constraints);
}
});
return c;
}
此方法取自JRootPane。它基本上是一个简单的JPanel,你可以看到自定义的布局管理器。
现在,您的示例中存在一些问题。
首先是调用顺序 - 您在向其中添加内容之前调整框架大小。只需更改订单,您就会看到滚动窗格:
public class MyFrame extends JFrame
{
public MyFrame ()
{
super();
// Add components first
initComponents ();
// Setup frame after so it fits its new content
setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
setPreferredSize ( new Dimension ( 500, 300 ) );
setResizable ( false );
pack ();
setLocationRelativeTo ( null );
}
private void initComponents ()
{
JPanel panel = new JPanel ();
panel.setLayout ( new BoxLayout ( panel, BoxLayout.Y_AXIS ) );
for ( int i = 0; i < 100; i++ )
{
panel.add ( new JLabel ( "some text" ) );
}
JScrollPane scrollPane =
new JScrollPane ( panel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER );
// Here I create a JPanel to replace the contentPane of JFrame
JPanel contentPane = new JPanel ();
contentPane.add ( scrollPane );
setContentPane ( contentPane );
}
public static void main ( String[] args )
{
SwingUtilities.invokeLater ( new Runnable ()
{
public void run ()
{
new MyFrame ().setVisible ( true );
}
} );
}
}
它仍然会有所不同,因为您的new JPanel ()
默认使用FlowLayout
,而不是默认内容窗格组件使用的BorderLayout
:
只需设置BorderLayout
即可获得您想要查看的结果:
JPanel contentPane = new JPanel ( new BorderLayout () );
答案 1 :(得分:1)
看看Rob Camick的WrapLayout,这是FlowLayout的扩展
import java.awt.*;
import javax.swing.*;
public class TestWrapLayout {
public TestWrapLayout () {
ImageIcon icon = new ImageIcon(getClass().getResource("/resources/stackoverflow2.png"));
JPanel panel = new JPanel(new WrapLayout());
for (int i = 1; i <= 250; i++) {
JLabel iconlabel = new JLabel(icon);
iconlabel.setLayout(new BorderLayout());
JLabel textlabel = new JLabel(String.valueOf(i));
textlabel.setHorizontalAlignment(JLabel.CENTER);
textlabel.setForeground(Color.WHITE);
textlabel.setFont(new Font("impact", Font.PLAIN,20));
iconlabel.add(textlabel);
panel.add(iconlabel);
}
JFrame frame = new JFrame();
frame.add(new JScrollPane(panel));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
new TestWrapLayout();
}
});
}
}
答案 2 :(得分:0)
答案 3 :(得分:0)
首先,创建第二个面板的原因是什么?那里
已经是第一个以BoxLayout
作为布局的面板
经理集。只需设置具有第一个面板的滚动窗格
如父母按预期工作。
你要么打电话
setContentPane(scrollPane);
或
add(scrollPane);
现在我要解释导致这种意外行为的原因。这个 是一种怪癖,有时会发生在使用嵌套技术的人身上 在构建布局时。使用嵌套时,布局可以 相互影响。
选择另一个布局 - FlowLayout
- 作为底层基础布局,
您导致第一个面板以其首选大小显示。代替
一个面板,你现在有两个面板,基板影响了
带标签的面板 - 它控制着它的大小。 FlowLayout
显示所有孩子的首选大小;它不尊重mimimum也不尊重
最大尺寸。因此,(第一个)可见面板的大小可以显示其所有标签;
这是计算首选大小的方式 - 足够大以显示所有大小
儿童。然而,有100个标签,它是非常大的;布局被打破了。它是
垂直那么大,我们实际上无法到达窗户的底部。
因此,通过我们的可见面板显示其所有标签,展示的目的是什么 verticall滚动条?不需要,因为所有标签都是“可见的”(放在上面 窗户区域,虽然设计被打破了。
所以问题不在于滚动条;他们正常工作。如果你
设置(在您的示例中)垂直滚动条策略为VERTICAL_SCROLLBAR_ALWAYS
你会看到滚动条但没有滑块,因为所有标签都是“可见的”
而且没有什么可滚动的。 (滚动条显示隐藏的内容
布局。)问题在于FlowLayout
仅以首选大小显示其组件。
以下是一个按预期工作的固定代码示例:
package com.zetcode;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
public class MyFrame extends JFrame {
public MyFrame() {
initComponents();
setTitle("Scrollbar");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setPreferredSize(new Dimension(300, 200));
pack();
setLocationRelativeTo(null);
}
private void initComponents() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
for (int i=0; i < 100; i++)
panel.add(new JLabel("some text"));
JScrollPane scrollPane = new JScrollPane(panel,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
setContentPane(scrollPane);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MyFrame ex = new MyFrame();
ex.setVisible(true);
}
});
}
}