编写一个将遵循GridBagLayout的JPanel子类? [英] Writing a JPanel subclass that will obey GridBagLayout?

查看:93
本文介绍了编写一个将遵循GridBagLayout的JPanel子类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我建立了一个扩展JPanel的类,并且每次都在上面设置大小.但是现在我需要在另一个面板上存在该JPanel子类的多个实例.我正在使用GridBagLayout,但是当我调整Frame的大小或从JPanel子类中删除setSize(800,100)时,我的组件消失了.我该如何构建符合这些layout managers的组件?

I built a class that extends JPanel, and I have been setting a size on it every time. But now I need multiple instances of that JPanel sub-class to exist on another panel. I am using GridBagLayout, but my components disappear when I resize the Frame or take away the setSize(800,100) from the JPanel subclass. How do I built components that will obey these layout managers?

我希望我的自定义组件能够适应布局管理器要求的尺寸.

I want my custom component to be able to fit to the size that the layout manager asks for.

这是我的自定义组件

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将它们添加到容器中

And here is how I am adding them to the container using 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);


    }

当我执行应该添加的操作已执行"操作时,我的自定义组件会显示在左上角,但是我必须调整窗口大小才能显示所有组件.

When I do this "action performed" that is supposed to add it, my custom component shows up in the top left corner, but I have to resize the window to get all the components to show.

推荐答案

许多布局管理器都使用getPreferredSizegetMinimumSizegetMaximumSize返回的值.

Many layout managers make use of the values returned by getPreferredSize, getMinimumSize and getMaximumSize.

GridBagLayout是其中的一种,通常会在可能的情况下尝试并尊重这三者.

GridBagLayout is one of those which will, generally, where possible, try and honor all three.

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

In your custom component, override (at least), the getPreferredSize method and return, to the best of you knowledge, the size of the component you need.

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

If the component is using a layout manager with other components in it, you should always let the layout manager make this determination (which is the default behavior)

已更新

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

Don't forget, when adding or removing components, you may be required to call revalidate to force the container hierarchy to update it's layout(s)

这篇关于编写一个将遵循GridBagLayout的JPanel子类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆