【问题标题】:How To Dynamically Add Elements To a JScrollPanel?如何动态地将元素添加到 JScrollPane?
【发布时间】:2016-06-24 20:02:51
【问题描述】:

我正在尝试使用 Java 中的 Swing 制作一个 GUI,它执行以下操作:

当按下“添加”按钮时,会创建一个 JPanel 并填满 GUI 的整个宽度。 JPanel 内部将使用 FlowLayout 排列 JLabels,这些 JLabel 会告诉您具体的详细信息(即名称、用户 ID 等)。每当随后按下“添加”按钮时,我希望在前一个下方添加一个新的 JPanel,以便 JScrollPane 将在必要时激活其垂直滚动条。基本上,我希望 JScrollPane 能够在其中动态添加新的 JPanel。

但是,我在尝试执行此操作时遇到了几个问题。我无法弄清楚 JScrollPane 中的面板使用哪个 LayoutManager。我尝试过使用 GridlLayout,但这似乎不起作用,因为当有足够的 JPanel 来覆盖整个 JScrollPane 时,GridLayout 只会创建一个新列来压缩新的 JPanel,而不是将其添加到之前的 JPanel 下方。我应该怎么做才能实现这一目标?以下是我所拥有的一些图像以及我想要发生的事情的一个示例。

这是我想要发生的事情:

任何帮助将不胜感激,在此先感谢您! :)

编辑:这是我尝试使用 GridLayout 的代码示例。

public Window() {


    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 701, 400);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    contentPane.setLayout(new BorderLayout(0, 0));
    setContentPane(contentPane);

    JPanel buttonPanel = new JPanel();
    contentPane.add(buttonPanel, BorderLayout.SOUTH);

    JButton btnAdd = new JButton("Add");
    buttonPanel.add(btnAdd);

    JScrollPane scrollPane = new JScrollPane();
    contentPane.add(scrollPane, BorderLayout.CENTER);

    JPanel systemsPanel = new JPanel();
    scrollPane.setViewportView(systemsPanel);
    systemsPanel.setLayout(new GridLayout(8, 1, 0, 0)); //8 rows for now



    for (int i = 1; i < 50; i++) {
        systemsPanel.add(new JButton("test"), "cell 0 " + i);
    }
    Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
    this.setLocation(dim.width / 2 - this.getSize().width / 2, dim.height / 2 - this.getSize().height / 2); //Center the Frame 

}

【问题讨论】:

  • 请创建并发布一个有效的minimal reproducible example 以获得快速获得最佳帮助的最佳机会。此代码将很小、独立,并作为代码格式的文本与您的问题一起发布在此处,而不是在链接中。祝你好运!
  • 而且 GridLayout 应该可以正常工作,但您可能没有正确使用它。再次向我们展示您如何在代码中使用它。另外,您确定不想使用 JTable 吗?
  • 如前所述,您应该使用JTable。您将无法使用 FlowLayout 在面板中定位每个组件。那就是您的组件不会在列中对齐,因为每个组件的大小可能不同。请参阅How to Use Tables 了解更多信息。
  • 但是看看你的 GUI,你真的很想使用 JTable,它的列对应于类型、地址、用户 ID 和第二种类型。
  • I still want other elements such as JButtons - 见Table Button Column

标签: java swing user-interface jpanel jscrollpane


【解决方案1】:

如果您想将 JPanel 行添加到 GUI 中,我会将它们放在使用 GridLayout(0, 1) 或 (0, 1, x, y) 的 JPanel 中。 0 表示可变的行数,1 表示 1 列,x 和 y 是垂直和水平间隙。然后,我将其放入使用 JPanel 的 BorderLayout 到 NORTH 位置,这样行就不会像他们想要的那样扩展以填充滚动窗格的视口。我会将第二个包装 JPanel 放入 JScrollPane 的视口中。

添加任何组件后,我会在容器上调用 revalidate 并重新绘制,以便其布局管理器将激活并正确放置新组件,并重新绘制以消除可能徘徊的任何脏像素(在删除时更重要组件)。

例如,我的 MCVE:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;

import javax.swing.*;

public class AddRowA extends JPanel {
    private static final int PREF_W = 650;
    private static final int PREF_H = 400;

    // JPanel to hold all rows. uses gridlayout that has 1 column and variable number
    // of rows
    private JPanel rowHolderPanel = new JPanel(new GridLayout(0, 1, 1, 1));

    public AddRowA() {
        // outerPanel is a wrapper or container JPanel that is 
        // held by JScrollPane's viewport that holds the rowHolderPanel in 
        // a BorderLayout.PAGE_START location, so the rows don't expand unnecessarily
        JPanel outerPanel = new JPanel(new BorderLayout());
        outerPanel.add(rowHolderPanel, BorderLayout.PAGE_START);
        JScrollPane scrollPane = new JScrollPane(outerPanel);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        JPanel addPanel = new JPanel();
        addPanel.add(new JButton(new AddAction("Add")));

        setLayout(new BorderLayout());
        add(scrollPane, BorderLayout.CENTER);
        add(addPanel, BorderLayout.PAGE_END);
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }

    private class AddAction extends AbstractAction {
        public AddAction(String name) {
            super(name);
            int mnemonic = (int) name.charAt(0);
            putValue(MNEMONIC_KEY, mnemonic);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            JPanel panel = new JPanel();
            panel.add(new JLabel("Foo"));
            panel.add(Box.createHorizontalStrut(25));
            panel.add(new JButton("Bar"));
            panel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));

            rowHolderPanel.add(panel);
            rowHolderPanel.revalidate();
            rowHolderPanel.repaint();
        }
    }

    private static void createAndShowGui() {
        JFrame frame = new JFrame("Add Row A");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new AddRowA());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

但是,您最好使用 JTable... 例如:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;

public class AddRowB extends JPanel {
    private MyTableModel tableModel = new MyTableModel();
    private JTable table = new JTable(tableModel);

    public AddRowB() {
        JPanel addPanel = new JPanel();
        addPanel.add(new JButton(new AddAction("Add")));

        setLayout(new BorderLayout());
        add(new JScrollPane(table));
        add(addPanel, BorderLayout.PAGE_END);
    }

    private class AddAction extends AbstractAction {
        public AddAction(String name) {
            super(name);
            int mnemonic = (int) name.charAt(0);
            putValue(MNEMONIC_KEY, mnemonic);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            RowData row = new RowData("Type", "Address", "User ID");
            tableModel.addRow(row);
        }
    }

    private static void createAndShowGui() {
        JFrame frame = new JFrame("Add Row B");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new AddRowB());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

class MyTableModel extends DefaultTableModel {
    private static final String[] COLUMNS = {"Type", "Address", "User ID"};

    public MyTableModel() {
        super(COLUMNS, 0);
    }

    public void addRow(RowData rowData) {
        Object[] row = {
                rowData.getType(),
                rowData.getAddress(),
                rowData.getUserID()
        };
        addRow(row);
    }
}

class RowData {
    String type;
    String address;
    String userID;

    public RowData(String type, String address, String userID) {
        this.type = type;
        this.address = address;
        this.userID = userID;
    }

    public String getType() {
        return type;
    }

    public String getAddress() {
        return address;
    }

    public String getUserID() {
        return userID;
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-01
    • 2016-01-01
    • 2011-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-31
    • 1970-01-01
    相关资源
    最近更新 更多