gpt4 book ai didi

java - 在列表中组织 JPanel 的最佳方式是什么?

转载 作者:行者123 更新时间:2023-11-30 07:12:18 25 4
gpt4 key购买 nike

我发现自己最近写了很多程序,它们都需要显示一些数据集合。到目前为止,我想到的最好看的方法是制作小的 JPanel,其中包含集合中每个项目的数据,并将它们全部放在一个大的 JPanel 中,然后我将其放入 JScrollPane 中。它的工作和外观都符合预期,但有一个问题:我似乎无法让较小的 JPanel 从较大的 JPanel 的顶部开始。

Example

只有当我将少量小 JPanel(绿色)添加到较大的 JPanel(红色)中时,问题才会明显。

下面描述的是我用来生成上述内容的方法,我想知道是否有更好的方法可以做到这一点(列表应该从顶部开始):

  • 我创建了一个扩展 JPanel 的类,并在其中添加了我想要显示的所有数据。我们称它为“SmallPanel.java”。我没有设置它的大小(稍后出现)。

  • 在我的主窗口类(扩展 JFrame)中:

    private JScrollPane scrollPane;
    private JPanel panel;
    ...
    scrollPane = new JScrollPane();
    getContentPane().add(scrollPane);

    panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    scrollPane.setViewportView(panel);
    ...
    private void addPanel()
    {
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 0;
    gbc.gridy = panel.getComponentCount(); //The new JPanel's place in the list
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.anchor = GridBagConstraints.PAGE_START; //I thought this would do it
    gbc.ipady = 130; //Set the panel's height, the width will get set to that of the container JPanel (which is what I want since I'd like my JFrames to be resizable)
    gbc.insets = new Insets(2, 0, 2, 0); //Separation between JPanels in the list
    gbc.weightx = 1.0;
    SmallPanel smallPanel = new SmallPanel();
    panel.add(smallPanel, gbc);
    panel.revalidate();
    panel.invalidate();
    panel.repaint(); //Better safe than peeved
    }
  • 每次我想添加面板时调用 addPanel() 方法。

编辑

最终解决方案(基于下面 MadProgrammer 的回答):

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.BevelBorder;

public class ListPanel extends JPanel
{
private static final long serialVersionUID = 1L;
private JPanel fillerPanel;
private ArrayList<JPanel> panels;

public ListPanel(List<JPanel> panels, int height)
{
this(panels, height, new Insets(2, 0, 2, 0));
}

public ListPanel(List<JPanel> panels, int height, Insets insets)
{
this();
for (JPanel panel : panels)
addPanel(panel, height, insets);
}

public ListPanel()
{
super();
this.fillerPanel = new JPanel();
this.fillerPanel.setMinimumSize(new Dimension(0, 0));
this.panels = new ArrayList<JPanel>();
setLayout(new GridBagLayout());
}

public void addPanel(JPanel p, int height)
{
addPanel(p, height, new Insets(2, 0, 2, 0));
}

public void addPanel(JPanel p, int height, Insets insets)
{
super.remove(fillerPanel);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = getComponentCount();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.PAGE_START;
gbc.ipady = height;
gbc.insets = insets;
gbc.weightx = 1.0;
panels.add(p);
add(p, gbc);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = getComponentCount();
gbc.fill = GridBagConstraints.VERTICAL;
gbc.weighty = 1.0;
add(fillerPanel, gbc);
revalidate();
invalidate();
repaint();
}

public void removePanel(JPanel p)
{
removePanel(panels.indexOf(p));
}

public void removePanel(int i)
{
super.remove(i);
panels.remove(i);
revalidate();
invalidate();
repaint();
}

public ArrayList<JPanel> getPanels()
{
return this.panels;
}

public static void main(String[] args)
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setMinimumSize(new Dimension(500, 500));
f.setLocationRelativeTo(null);
f.getContentPane().setLayout(new BorderLayout());
final ListPanel listPanel = new ListPanel();
for (int i = 1; i <= 10; i++)
listPanel.addPanel(getRandomJPanel(), new Random().nextInt(50) + 50);
JButton btnAdd = new JButton("Add");
btnAdd.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent paramActionEvent)
{
listPanel.addPanel(getRandomJPanel(), new Random().nextInt(50) + 50);
}
});
JButton btnRemove = new JButton("Remove");
btnRemove.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent paramActionEvent)
{
listPanel.removePanel(0);
}
});
f.getContentPane().add(btnRemove, BorderLayout.NORTH);
f.getContentPane().add(btnAdd, BorderLayout.SOUTH);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scrollPane.setViewportView(listPanel);
f.getContentPane().add(scrollPane, BorderLayout.CENTER);
f.setVisible(true);
}

public static JPanel getRandomJPanel()
{
JPanel panel = new JPanel();
panel.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
panel.add(new JLabel("This is a randomly sized JPanel"));
panel.setBackground(new Color(new Random().nextFloat(), new Random().nextFloat(), new Random().nextFloat()));
return panel;
}
}

最佳答案

我发现的最佳解决方案是使用 SwingLabs SwingX(可以从 here 下载)库中的 VerticalLayout

您“可以”使用 GridBagLayout,在末尾放置一个不可见的组件,其 weighty 属性设置为 1,但这需要管理更多的额外工作,因为您需要不断更新所有组件的 x/y 位置以使其保持在原位...

更新了 GridBagLayout 示例

enter image description here

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class VerticalLayoutExample {

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

public VerticalLayoutExample() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}

final TestPane pane = new TestPane();
JButton add = new JButton("Add");
add.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
pane.addAnotherPane();
}
});

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(pane));
frame.add(add, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public class TestPane extends JPanel {

private JPanel filler;
private int y = 0;

public TestPane() {

setBackground(Color.RED);
setLayout(new GridBagLayout());

filler = new JPanel();
filler.setOpaque(false);
GridBagConstraints gbc = new GridBagConstraints();
gbc.weighty = 1;
gbc.gridy = 0;

add(filler, gbc);

}

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

public void addAnotherPane() {

JPanel panel = new JPanel(new GridBagLayout());
panel.add(new JLabel("Hello"));

GridBagConstraints gbc = new GridBagConstraints();
gbc.gridy = y++;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.insets = new Insets(4, 4, 4, 4);

add(panel, gbc);

GridBagLayout gbl = ((GridBagLayout)getLayout());
gbc = gbl.getConstraints(filler);
gbc.gridy = y++;
gbl.setConstraints(filler, gbc);

revalidate();
repaint();

}
}
}

这只是一个概念。正如 camickr 指出的那样,只要您知道最后一个组件,就可以调整组件的 GridBagConstraints 以便列表中的最后一个组件具有 weighty 1 而不是...

如您所愿,您可以覆盖 GridBagLayout 所做的一些事情,例如,我要求 GridBagLayout 代替使用面板的首选大小让它填充父容器的 HORIZONTAL 宽度...

关于java - 在列表中组织 JPanel 的最佳方式是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20487329/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com