简体   繁体   English

java JPanel,向其和JScrollPane动态添加组件

[英]java JPanel, dynamically adding components to it and JScrollPane

We've been experimenting around with this but without luck, please note I'm probably using the components the wrong way... We've got a JFrame cointaining a JPanel , which contains a JScrollPane with another JPanel inside of it, called interiorPanel . 我们一直在尝试这种方法,但是没有运气,请注意,我可能以错误的方式使用了组件...我们有一个JFrame包含一个JPanel ,其中包含一个JScrollPane ,其中包含另一个JPanel,称为interiorPanel Having a JButton with an action that adds components dynamically to the innermost panel and then calls its revalidate() method, interiorPanel grows like we need inside of the JScrollPane, showing its scroll bars like this: 有了一个JButton ,它的动作可以动态地将组件添加到最里面的面板,然后调用其revalidate()方法, interiorPanel面板会像我们需要的那样在JScrollPane interiorPanel增长,显示其滚动条如下:

理想的情况

However, we want to add components with a loop instead of using a button. 但是,我们希望使用循环而不是使用按钮来添加组件。 Using this loop: 使用此循环:

for (int i = 1; i < 10; i++) {
    demo.getPanelInterior().add(new JButton("Hello"));
    demo.getPanelInterior().revalidate();
    demo.getPanelInterior().repaint();
}

doesn't seem to work like in the case when we click the button since the innermost panel grows, but the scroll bars don't show up, so we end with something like this: 由于最里面的面板变大了,所以似乎不像单击按钮时那样工作,但是滚动条没有显示出来,所以我们以这样的结尾:

不良影响

What should we do to get the result from the first image? 我们应该怎么做才能从第一张图片中得到结果? Here's the working example code: 这是工作示例代码:

    import java.awt.*;
    import java.awt.event.*;

    import javax.swing.*;


    public class Demo extends JPanel {

        private JPanel exteriorPanel;
        private JPanel interiorPanel;
        private JButton button;
        private JList<String> list;
        private String[] imageNames = { "Bird", "Cat", "Dog", "Rabbit", "Pig", "dukeWaveRed",
        "kathyCosmo", "lainesTongue", "left", "middle", "right", "stickerface"};
        private DefaultListModel<String> model;



        public Demo() {

            //Create the list of images and put it in a scroll pane.

            model = new DefaultListModel<>();
            for (String s : imageNames) {
                model.addElement(s);
            }

            list = new JList<String>(model);
            list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            list.setSelectedIndex(0);

            JScrollPane listScrollPane = new JScrollPane();
            listScrollPane.setViewportView(list);

            button = new JButton("Add element");
            button.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    buttonActionPerformed(e);
                }
            });

        interiorPanel = new JPanel();
        interiorPanel.add(listScrollPane);
        interiorPanel.add(button);
        interiorPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 2, 2));

        JScrollPane anotherScroll = new JScrollPane();
        anotherScroll.setViewportView(interiorPanel);

        exteriorPanel = new JPanel();
        exteriorPanel.add(anotherScroll);
        exteriorPanel.setPreferredSize(new Dimension(400, 200));

        interiorPanel.setBackground(new Color(255, 0, 0));


    }

    private void buttonActionPerformed(ActionEvent e) {
        model.addElement("Hola");
        interiorPanel.add(new JButton("Hello"));
        interiorPanel.revalidate();
    }

    //Used by SplitPaneDemo2
    public JList getImageList() {
        return list;
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {

        //Create and set up the window.
        JFrame frame = new JFrame("Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Demo demo = new Demo();
        frame.getContentPane().add(demo.getExteriorPanel());

        //Display the window.
        frame.pack();
        frame.setVisible(true);

        for (int i = 1; i < 10; i++) {
            demo.getPanelInterior().add(new JButton("Hello"));
            demo.getPanelInterior().revalidate();
            demo.getPanelInterior().repaint();
        }


    }

    public JPanel getExteriorPanel() {
        return exteriorPanel;
    }

    public JPanel getPanelInterior() {
        return interiorPanel;
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }


}

Thanks in advance 提前致谢

The (main) problem is to do with the exteriorPanel 's use of FlowLayout , which is allowing it to expand to meet the requirements of the JScrollPane , which will try and use the preferred size of it's contents as a base for it's own layout calculations...this is compounding to produce the result you are seeing. (主要)问题与exteriorPanelFlowLayout的使用有关,这使它可以扩展以满足JScrollPane的要求, JScrollPane会尝试使用其内容的首选大小作为自身布局计算的基础。 ...这会使您看到的结果更加复杂。 In fact, even when using the "click button", this will happen if you try resizing the window... 实际上,即使使用“单击按钮”,如果您尝试调整窗口的大小也会发生这种情况。

Instead, try changing the layout manager of the exteriorPanel , for example... 相反,请尝试更改exteriorPanel面板的布局管理器,例如...

exteriorPanel = new JPanel(new BorderLayout());

This will force the scrollpane to meet the requirements of the parent container and then will allow the view to overflow its bounds and display the scrollbars... 这将强制滚动窗格满足父容器的要求,然后将允许视图溢出其边界并显示滚动条...

使用边框布局

You should also have a read through Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing? 您还应该通读我是否应该避免在Java Swing中使用set(Preferred | Maximum | Minimum)Size方法?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM