Java 如何向JScrollPanel动态添加元素?
我正在尝试使用Java中的Swing制作一个GUI,它可以执行以下操作: 当按下“添加”按钮时,将创建一个JPanel并填充整个GUI宽度。在JPanel内部,将使用告诉特定细节(即名称、用户ID等)的FlowLayout安排JLabel。无论何时按下Add按钮,我都希望在上一个按钮的正下方添加一个新的JPanel,以便JScrollPane在必要时激活其垂直滚动条。基本上,我希望JScrollPane能够在其中动态添加新的JPanel 然而,我在尝试这样做时遇到了一些问题。在JScrollPane中,我无法确定要为面板使用哪个LayoutManager。我尝试过使用GridlLayout,但这似乎不起作用,因为当有足够多的JPanel覆盖整个JScrollPane时,GridLayout只会创建一个新列,在新的JPanel中挤压,而不是将其添加到以前的JPanel下面。为了实现这一目标,我应该做些什么?以下是我所拥有的一些图片和我希望发生的事情的一个例子 以下是我希望发生的事情: 如果您有任何帮助,我们将不胜感激,提前谢谢您!:) 编辑:下面是我用GridLayout尝试的代码示例Java 如何向JScrollPanel动态添加元素?,java,swing,user-interface,jpanel,jscrollpane,Java,Swing,User Interface,Jpanel,Jscrollpane,我正在尝试使用Java中的Swing制作一个GUI,它可以执行以下操作: 当按下“添加”按钮时,将创建一个JPanel并填充整个GUI宽度。在JPanel内部,将使用告诉特定细节(即名称、用户ID等)的FlowLayout安排JLabel。无论何时按下Add按钮,我都希望在上一个按钮的正下方添加一个新的JPanel,以便JScrollPane在必要时激活其垂直滚动条。基本上,我希望JScrollPane能够在其中动态添加新的JPanel 然而,我在尝试这样做时遇到了一些问题。在JScrollPa
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
}
公共窗口(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
立根(100100701400);
contentPane=newjpanel();
setboorder(新的EmptyBorder(5,5,5,5));
setLayout(新的BorderLayout(0,0));
setContentPane(contentPane);
JPanel buttonPanel=新的JPanel();
添加(buttonPanel,BorderLayout.SOUTH);
JButton btnAdd=新JButton(“添加”);
按钮面板添加(btnAdd);
JScrollPane scrollPane=新的JScrollPane();
添加(滚动窗格,BorderLayout.CENTER);
JPanel systemsPanel=新的JPanel();
scrollPane.setViewportView(systemsPanel);
setLayout(新的GridLayout(8,1,0,0));//现在有8行
对于(int i=1;i<50;i++){
systemsPanel.add(新JButton(“测试”),“单元格0”+i);
}
维度dim=Toolkit.getDefaultToolkit().getScreenSize();
this.setLocation(dim.width/2-this.getSize().width/2,dim.height/2-this.getSize().height/2);//使框架居中
}
如果您想将行JPanel添加到GUI中,我会将它们放在使用GridLayout(0,1)或(0,1,x,y)的JPanel中。0表示行数可变,1表示1列,x和y表示垂直和水平间隙。然后,我将使用JPanel将其放置到BorderLayout中的NORTH位置,这样行就不会像它们希望的那样展开以填充scrollpane的视口。我将第二个包装器JPanel放入JScrollPane的视口中
添加任何组件后,我将调用容器上的revalidate和repait,以便其布局管理器能够激活并正确放置新组件,并重新绘制以去除可能挂起的任何脏像素(在移除组件时更为重要)
例如,我的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;
}
}
如果您想将行JPanel添加到GUI中,我会将它们放在使用GridLayout(0,1)或(0,1,x,y)的JPanel中。0表示行数可变,1表示1列,x和y表示垂直和水平间隙。然后,我将使用JPanel将其放置到BorderLayout中的NORTH位置,这样行就不会像它们希望的那样展开以填充scrollpane的视口。我将第二个包装器JPanel放入JScrollPane的视口中 添加任何组件后,我将调用容器上的revalidate和repait,以便其布局管理器能够激活并正确放置新组件,并重新绘制以去除可能挂起的任何脏像素(在移除组件时更为重要) 例如,我的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;
}
}
请创建并发布一个有效的链接,以便快速获得最佳帮助。这段代码将是小的,自立的,并张贴在这里作为代码格式的文本与您的问题,而不是在一个链接。祝你好运GridLayout应该可以正常工作,但您可能没有正确使用它。再次向我们展示如何在代码中使用它。另外,您确定不想使用JTable吗?如前所述,您应该使用
JTable
。您将无法使用FlowLayout在面板中定位每个组件。也就是说,您的组件不会在列中对齐,因为每个组件的大小可能不同。有关更多信息,请参阅。但查看您的GUI,您似乎真的很想使用JTable,它的列对应于类型、地址、用户id和第二种类型。我仍然需要其他元素,如JButtons
-请参阅。请创建并发布一个有效的JTable,以便快速获得最佳帮助。这段代码将是小的,自立的,并张贴在这里作为代码格式的文本与您的问题,而不是在一个链接。祝你好运GridLayout应该可以正常工作,但您可能没有正确使用它。再次向我们展示如何在代码中使用它。另外,您确定不想使用JTable吗?如前所述,您应该使用JTable
。您将无法使用FlowLayout在面板中定位每个组件。也就是说,您的组件不会在列中对齐,因为每个组件的大小可能不同。有关更多信息,请参阅。但查看GUI,您似乎真的很想使用JTable,它的列对应于类型、地址、用户id和第二种类型。我仍然需要其他元素,如JButtons
-请参阅。