最终使用滚动条的JPanel列表

5
我正在尝试为我的Java应用程序构建GUI界面。 我动态添加JPanels,它们是我的GUI中的“行”。在Panel列表下面有一个按钮,用于添加新的Panel。随着List的增长,它将到达父容器的末尾。然后,我想使用滚动条,以便用户能够访问列表中的每个panel。
到目前为止,我已经尝试使用JScrollPanes和布局,但我不知道如何使其工作。
你能给我一些建议吗?
this.setLayout(new BorderLayout());
JPanel listContainer = new JPanel();
listContainer.setLayout(BoxLayout(listContainer, BoxLayout.Y_AXIS);

this.add(new JScrollPane(listContainer), BorderLayout.CENTER);
this.add(new JButton(), BorderLayout.PAGE_END);

//then i add panels to the listContainer. this wont work, when the space is complettly used there is no scrollbar.

BoxLayout 可能不是最好的选择 - 在我看来 - MadProgrammer
jScrollPane1.getViewport().add(yourpanel) - sasankad
@sasankad OP(原帖作者)可能正在将新面板添加到“listContainer”中,而该容器已经被添加到滚动窗格中。 - MadProgrammer
@MadProgrammer 是的,这就是我正在做的。 - Horstinator
2个回答

13

从你的代码片段中很难确定你可能遇到的问题。

这里输入图片描述

public class DynamicPanelList {

    public static void main(String[] args) {
        new DynamicPanelList();
    }

    public DynamicPanelList() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JPanel mainList;

        public TestPane() {
            setLayout(new BorderLayout());

            mainList = new JPanel(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.weightx = 1;
            gbc.weighty = 1;
            mainList.add(new JPanel(), gbc);

            add(new JScrollPane(mainList));

            JButton add = new JButton("Add");
            add.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JPanel panel = new JPanel();
                    panel.add(new JLabel("Hello"));
                    panel.setBorder(new MatteBorder(0, 0, 1, 0, Color.GRAY));
                    GridBagConstraints gbc = new GridBagConstraints();
                    gbc.gridwidth = GridBagConstraints.REMAINDER;
                    gbc.weightx = 1;
                    gbc.fill = GridBagConstraints.HORIZONTAL;
                    mainList.add(panel, gbc, 0);

                    validate();
                    repaint();
                }
            });

            add(add, BorderLayout.SOUTH);

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }
    }
}

你真的需要提供一个SSCCE,这将使我们能够诊断您遇到的问题。

个人认为,这将取决于您的要求,一个更好的布局管理器可能是SwingLabs SwingX库中的VerticalLayout


+1。有趣的是我们得出了几乎相同的结论,甚至几乎相同的例子;-) - Guillaume Polet
@GuillaumePolet 经验指导:D +1,你的回答也很好。 - MadProgrammer
在JLabel中,当文本水平增长时,是否可以将文本分行显示? - digz6666
@digz6666 一般来说,有几种方法可以实现,个人而言,我会将文本包装在HTML标签中。 - MadProgrammer
@MadProgrammer 除了使用HTML标签,还有其他的方法吗?我在这里提出了问题:http://stackoverflow.com/questions/40957446/make-jlabel-text-breaks-in-gridbaglayout - digz6666
@digz6666 不是很好,比如这个例子和这个例子。或者,您可以简化一个JTextArea,使其只读并使用它代替。 - MadProgrammer

4
你可能忘记在你的listContainer上调用revalidate()(并且还有一堆语法错误)。我认为,BoxLayout 做得并不好,但这不是问题所在。
下面是一个小的演示代码,它似乎运行得相当不错:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestScollpane {
    private int i;
    private JPanel listContainer;

    private void initUI() {
        final JFrame frame = new JFrame(TestScollpane.class.getSimpleName());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        listContainer = new JPanel();
        listContainer.setLayout(new BoxLayout(listContainer, BoxLayout.Y_AXIS));

        frame.add(new JScrollPane(listContainer), BorderLayout.CENTER);
        JButton button = new JButton("Add");
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                final JPanel newPanel = new JPanel();
                newPanel.add(new JLabel("Label " + i++));
                listContainer.add(newPanel);
                listContainer.revalidate();
                // Scroll down to last added panel
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        newPanel.scrollRectToVisible(newPanel.getBounds());
                    }
                });
            }
        });
        frame.add(button, BorderLayout.PAGE_END);

        frame.setSize(300, 200);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (UnsupportedLookAndFeelException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestScollpane().initUI();
            }
        });
    }
}

好的,你的演示对我也有效。但是我不知道我在我的代码中做了什么不同的事情。据我所知,我做的一切都与你的例子相似:http://nopaste.info/719313cd1b.html - Horstinator
@Horstinator 很难判断你在 ShowPanelShowFrameShow 中具体有什么内容,需要看一下才能确定。 - Guillaume Polet
我将整个源代码上传到了我的服务器,如果可以的话,您可以查看一下:http://176.28.8.235/shows.tar - Horstinator
@Horstinator 新手错误:您有 this.add(new JScrollPane(panelContainer), BorderLayout.CENTER);,它将panelContainer包装在JScrollPane中,并将滚动窗格添加到MainPanel中。稍后,您有:this.add(panelContainer); 它从滚动窗格中删除panelContainer并直接将其添加到MainPanel中。删除第二个调用,它将按预期工作。 - Guillaume Polet
天啊,谢谢!我没看到那个。我测试了很多次,可能有点混淆了。感谢你的帮助! - Horstinator
1
@Horstinator 在这种情况下,调试器的使用非常方便。您可以立即看到父级问题。 - Guillaume Polet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接