我构建了一个扩展JPanel
的类,我每次都在设置一个大小。但是现在我需要在另一个面板上存在该JPanel
子类的多个实例。我正在使用GridBagLayout
,但当我调整Frame
的大小或从setSize(800,100)
子类中删除JPanel
时,我的组件会消失。如何构建符合这些layout managers
的组件?
我希望我的自定义组件能够适应布局管理器要求的大小。
这是我的自定义组件
public class GridPanel extends JPanel implements MouseMotionListener, MouseListener{
private Rectangle offdutyRect, sbRect, driveRect, onRect;
private int delta = 60;
private int[][] gridArray;
int draggedStartX = -1;
int draggedStartY = -1;
private int dutyStatusSpacing = 60;
private int totalSpacing = 80;
public GridPanel(){
super();
this.setSize(new Dimension(800, 100));//without this it doesn't display
this.addMouseMotionListener((MouseMotionListener) this);
this.addMouseListener(this);
int gridArrayColumns = 24*60/delta;
gridArray = new int[4][gridArrayColumns];
int r = 0;
int rHeight = this.getHeight()/4;
offdutyRect = new Rectangle(this.getX() + dutyStatusSpacing, this.getY() + r*rHeight, this.getWidth() - totalSpacing, rHeight);
r++;
sbRect = new Rectangle(this.getX() + dutyStatusSpacing, this.getY() + r*rHeight, this.getWidth() - totalSpacing, rHeight);
r++;
driveRect = new Rectangle(this.getX() + dutyStatusSpacing, this.getY() + r*rHeight, this.getWidth() - totalSpacing, rHeight);
r++;
onRect = new Rectangle(this.getX() + dutyStatusSpacing, this.getY() + r*rHeight, this.getWidth() - totalSpacing, rHeight);
Rectangle rect = null;
for(r = 0; r < gridArray.length; r++){
if(r == 0){
rect = offdutyRect;
}else if(r == 1){
rect = sbRect;
}else if(r == 2){
rect = driveRect;
}else if(r == 3){
rect = onRect;
}
//I haven't actually derived any of these things, just my best guesses.
int len = gridArray[r].length;
int width = (int) (rect.getWidth()/len);
rect.setSize((int)(width*len), (int) rect.getHeight());
}
}
public void paintComponent(Graphics g){
g.clearRect(this.getX(), this.getY(), this.getWidth(), this.getHeight());
//the center black bar for duty status "placeholders"
g.setColor(Color.black);
g.drawRect(getX(), getY(), getWidth() - 1, getHeight() - 1);
g.drawRect((int)offdutyRect.getX(), (int)offdutyRect.getY() + (int)offdutyRect.getHeight()/2, (int)offdutyRect.getWidth(), 1);
g.drawRect((int)sbRect.getX(), (int)sbRect.getY() + (int)sbRect.getHeight()/2, (int)sbRect.getWidth(), 1);
g.drawRect((int)driveRect.getX(), (int)driveRect.getY() + (int)driveRect.getHeight()/2, (int)driveRect.getWidth(), 1);
g.drawRect((int)onRect.getX(), (int)onRect.getY() + (int)onRect.getHeight()/2, (int)onRect.getWidth(), 1);
g.setColor(Color.pink);
g.drawRect((int)offdutyRect.getX(), (int)offdutyRect.getY(), (int)offdutyRect.getWidth(), (int)offdutyRect.getHeight());
g.drawRect((int)sbRect.getX(), (int)sbRect.getY(), (int)sbRect.getWidth(), (int)sbRect.getHeight());
g.drawRect((int)driveRect.getX(), (int)driveRect.getY(), (int)driveRect.getWidth(), (int)driveRect.getHeight());
g.drawRect((int)onRect.getX(), (int)onRect.getY(), (int)onRect.getWidth(), (int)onRect.getHeight());
//draw the array
g.setColor(Color.green);
Rectangle rect = null;
for(int r = 0; r < gridArray.length; r++){
if(r == 0){
rect = offdutyRect;
}else if(r == 1){
rect = sbRect;
}else if(r == 2){
rect = driveRect;
}else if(r == 3){
rect = onRect;
}
//I haven't actually derived any of these things, just my best guesses.
int len = gridArray[r].length;
int width = (int) (rect.getWidth()/len);
int height = (int) rect.getHeight() - 2;
for(int c = 0; c < gridArray[r].length; c++){
if(gridArray[r][c] == 1){
int x = (int) (rect.getX() + width*c);
int y = (int) rect.getY() + 2;
g.fillRect(x, y, width, height);
}
}
}
}
以下是我如何使用gridbag
将它们添加到容器中public void actionPerformed(ActionEvent e) {
System.out.println("action performed" + panels.size());
removeAll();
repaint();
panels.add(new GridPanel());
int r = 0;
GridBagConstraints c = new GridBagConstraints();
for(int i = 0; i < panels.size(); i++){
JLabel label = new JLabel("day " + i);
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = r;
this.add(label, c);
r++;
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = r;
c.fill = GridBagConstraints.HORIZONTAL;
this.add(panels.get(i), c);
r++;
}
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = r;
c.fill = GridBagConstraints.HORIZONTAL;
BufferedImage img = null;
try {
img = ImageIO.read(this.getClass().getResource("/res/add.png"));
} catch (IOException ex) { }
JButton addButton = new JButton();
addButton.setIcon(new ImageIcon(img));
addButton.addActionListener(this);
this.add(addButton, c);
}
当我执行“应该执行的操作”应该添加它时,我的自定义组件显示在左上角,但我必须调整窗口大小以显示所有组件。
答案 0 :(得分:4)
许多布局管理员都会使用getPreferredSize
,getMinimumSize
和getMaximumSize
返回的值。
GridBagLayout
是其中之一,通常会在可能的情况下尝试并尊重这三者。
在自定义组件中,覆盖(至少)getPreferredSize
方法,并根据您的知识返回所需组件的大小。
如果组件使用的布局管理器中包含其他组件,则应始终让布局管理器进行此确定(这是默认行为)
<强>更新强>
不要忘记,在添加或删除组件时,可能需要调用revalidate
来强制容器层次结构更新它的布局