2

我建立了一个扩展类JPanel,并且每次都在设置它的大小。但是现在我需要该JPanel子类的多个实例存在于另一个面板上。我正在使用GridBagLayout,但是当我调整大小FramesetSize(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);


    }

当我执行应该添加它的“执行操作”时,我的自定义组件显示在左上角,但我必须调整窗口大小以显示所有组件。

4

1 回答 1

4

许多布局管理器使用getPreferredSize,getMinimumSize和返回的值getMaximumSize

GridBagLayout是那些通常会在可能的情况下尝试并尊重所有三者的人之一。

在您的自定义组件中,覆盖(至少)getPreferredSize方法并返回,据您所知,您需要的组件的大小。

如果组件正在使用包含其他组件的布局管理器,则应始终让布局管理器做出此决定(这是默认行为)

更新

不要忘记,在添加或删除组件时,您可能需要调用revalidate以强制容器层次结构更新其布局

于 2013-07-04T00:45:47.403 回答