我正在尝试找到一种方法来创建没有布局管理器的JPanel列表。
我找到了几个关于SO的例子,为可滚动的JPanel列表提供了解决方案。问题。更具体地说,我从this thread开始研究它。
我当前的问题是,当我从列表中的JPanels中删除布局时,我遇到了问题。
它们被正确添加但是在需要时不会出现滚动条,并且面板开始重叠。
注意:我知道布局是首选,但我发现使用纯X,Y坐标和模型程序更直接。请不要因此而抨击我......
这是一个小工作示例(从this comment获取和修改):
import java.awt.BorderLayout;
import java.awt.Color;
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;
import javax.swing.border.MatteBorder;
public class JScrollPanels {
private int i;
private JPanel listContainer;
private void initUI() {
final JFrame frame = new JFrame(JScrollPanels.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.setLayout(null);
newPanel.setSize(272, 110);
JLabel name = new JLabel("Name " + i++);
name.setBounds(18, 13, 84, 21);
newPanel.setBorder(new MatteBorder(0, 0, 1, 0, Color.GRAY));
JLabel date = new JLabel("12/11/2014");
date.setBounds(10, 44, 123, 21);
JButton btn= new JButton(">");
btn.addActionListener( new NameListener(name, date) );
btn.setBounds(205, 44, 48, 30);
newPanel.add(name);
newPanel.add(date);
newPanel.add(btn);
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(272, 300);
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 JScrollPanels().initUI();
}
});
}
public class NameListener implements ActionListener {
private JLabel name;
private JLabel date;
public NameListener(JLabel name, JLabel date) {
this.name = name;
this.date = date;
}
public void actionPerformed(ActionEvent e) {
System.out.println("Clicked " + name.getText() + " on " + date.getText());
}
}
}
修改
使用此修复:
final JPanel newPanel = new JPanel(){
@Override
public Dimension getPreferredSize() {
return new Dimension(272, 110);
}
};
谢谢,mKorbel!
答案 0 :(得分:2)
同样,我仍然坚持我的主张,从长远来看,布局管理器将发挥最佳作用。例如,您的GUI可能会使用这样的东西:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.*;
import javax.swing.border.Border;
@SuppressWarnings("serial")
public class JScrollPanels2 extends JPanel {
private static final int PREF_W = 300;
private static final int PREF_H = 300;
private int i;
private JPanel listContainer;
public JScrollPanels2() {
JPanel outerWrapperPanel = new JPanel(new BorderLayout());
listContainer = new JPanel();
listContainer.setLayout(new BoxLayout(listContainer, BoxLayout.Y_AXIS));
outerWrapperPanel.add(listContainer, BorderLayout.PAGE_START);
JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 5, 0));
buttonPanel.add(new JButton(new AddAction("Add")));
setLayout(new BorderLayout());
add(new JScrollPane(outerWrapperPanel), BorderLayout.CENTER);
add(buttonPanel, 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 evt) {
listContainer.add(new CellPanel(i));
listContainer.revalidate();
listContainer.repaint();
i++;
}
}
private class CellPanel extends JPanel {
private final int gap = 4;
private int index;
private String name;
private Date date;
private final String format = "MM/dd/yyyy";
private SimpleDateFormat sdf = new SimpleDateFormat(format);
public CellPanel(int i) {
this.index = i;
this.name = "Name " + index;
setLayout(new GridBagLayout());
date = new Date();
Border emptyBorder = BorderFactory.createEmptyBorder(gap, gap, gap, gap);
Border lineBorder = BorderFactory.createLineBorder(Color.black);
setBorder(BorderFactory.createCompoundBorder(lineBorder, emptyBorder));
add(new JLabel(name), createGbc(0, 0));
add(new JLabel(""), createGbc(1, 0));
add(new JLabel(sdf.format(date)), createGbc(0, 1));
add(new JButton(new MyBtnAction(">")), createGbc(1, 1));
}
private GridBagConstraints createGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
if (x % 2 == 0) {
gbc.anchor = GridBagConstraints.WEST;
} else {
gbc.anchor = GridBagConstraints.EAST;
}
return gbc;
}
private class MyBtnAction extends AbstractAction {
public MyBtnAction(String name) {
super(name);
// int mnemonic = (int) name.charAt(0);
// putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent evt) {
System.out.println("Button pressed for " + name);
}
}
}
private static void createAndShowGui() {
JScrollPanels2 mainPanel = new JScrollPanels2();
JFrame frame = new JFrame("JScrollPanels2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
使用布局管理器的一个好处是它们的灵活性。如果您想要将新组件添加到内部JPanel,您可以轻松地这样做,而无需手动重新计算每个组件的其他位置(如果需要移位)。相反,让布局经理为您做繁重的工作。此外,虽然使用GUI的null布局在一个平台上可能看起来不错,但在大多数其他平台或屏幕分辨率上通常看起来很糟糕。