不可见的组件仍然占用空间JPanel [英] Invisible components still take up space JPanel

查看:553
本文介绍了不可见的组件仍然占用空间JPanel的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在JPanel中将一系列组件放在彼此之下,设置为GridLayout。
我需要暂时隐藏组件,但 setVisible(false)不会删除它,因为组件的空隙仍然存在。

I have a series of components underneath each other in a JPanel set as a GridLayout. I need to temporarily hide the components but setVisible(false) doesn't cut it, because there is still an empty gap where the components were.

有没有快速简便的方法呢?或者我是否必须保持JPanel的状态,删除组件,然后恢复它?

Is there a quick and easy way to do this? Or do I have to stay saving the state of the JPanel, removing the components, then restoring it?

SSCCE:

[GridLayout2.java]

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Insets;

public class GridLayout2 extends GridLayout 
{
  public GridLayout2() {
    this(1, 0, 0, 0);
  }

  public GridLayout2(int rows, int cols) {
    this(rows, cols, 0, 0);
  }

  public GridLayout2(int rows, int cols, int hgap, int vgap) {
    super(rows, cols, hgap, vgap);
  }

  public Dimension preferredLayoutSize(Container parent) {
    //System.err.println("preferredLayoutSize");
    synchronized (parent.getTreeLock()) {
      Insets insets = parent.getInsets();
      int ncomponents = parent.getComponentCount();
      int nrows = getRows();
      int ncols = getColumns();
      if (nrows > 0) {
        ncols = (ncomponents + nrows - 1) / nrows;
      } 
      else {
        nrows = (ncomponents + ncols - 1) / ncols;
      }
      int[] w = new int[ncols];
      int[] h = new int[nrows];
      for (int i = 0; i < ncomponents; i ++) {
        int r = i / ncols;
        int c = i % ncols;
        Component comp = parent.getComponent(i);
        Dimension d = comp.getPreferredSize();
        if (w[c] < d.width) {
          w[c] = d.width;
        }
        if (h[r] < d.height) {
          h[r] = d.height;
        }
      }
      int nw = 0;
      for (int j = 0; j < ncols; j ++) {
        nw += w[j];
      }
      int nh = 0;
      for (int i = 0; i < nrows; i ++) {
        nh += h[i];
      }
      return new Dimension(insets.left + insets.right + nw + (ncols-1)*getHgap(), 
          insets.top + insets.bottom + nh + (nrows-1)*getVgap());
    }
  }

  public Dimension minimumLayoutSize(Container parent) {
    System.err.println("minimumLayoutSize");
    synchronized (parent.getTreeLock()) {
      Insets insets = parent.getInsets();
      int ncomponents = parent.getComponentCount();
      int nrows = getRows();
      int ncols = getColumns();
      if (nrows > 0) {
        ncols = (ncomponents + nrows - 1) / nrows;
      } 
      else {
        nrows = (ncomponents + ncols - 1) / ncols;
      }
      int[] w = new int[ncols];
      int[] h = new int[nrows];
      for (int i = 0; i < ncomponents; i ++) {
        int r = i / ncols;
        int c = i % ncols;
        Component comp = parent.getComponent(i);
        Dimension d = comp.getMinimumSize();
        if (w[c] < d.width) {
          w[c] = d.width;
        }
        if (h[r] < d.height) {
          h[r] = d.height;
        }
      }
      int nw = 0;
      for (int j = 0; j < ncols; j ++) {
        nw += w[j];
      }
      int nh = 0;
      for (int i = 0; i < nrows; i ++) {
        nh += h[i];
      }
      return new Dimension(insets.left + insets.right + nw + (ncols-1)*getHgap(), 
          insets.top + insets.bottom + nh + (nrows-1)*getVgap());
    }
  }

  public void layoutContainer(Container parent) {
    //System.err.println("layoutContainer");
    synchronized (parent.getTreeLock()) {
      Insets insets = parent.getInsets();
      int ncomponents = parent.getComponentCount();
      int nrows = getRows();
      int ncols = getColumns();
      if (ncomponents == 0) {
        return;
      }
      if (nrows > 0) {
        ncols = (ncomponents + nrows - 1) / nrows;
      } 
      else {
        nrows = (ncomponents + ncols - 1) / ncols;
      }
      int hgap = getHgap();
      int vgap = getVgap();
      // scaling factors      
      Dimension pd = preferredLayoutSize(parent);
      double sw = (1.0 * parent.getWidth()) / pd.width;
      double sh = (1.0 * parent.getHeight()) / pd.height;
      // scale
      int[] w = new int[ncols];
      int[] h = new int[nrows];
      for (int i = 0; i < ncomponents; i ++) {
        int r = i / ncols;
        int c = i % ncols;
        Component comp = parent.getComponent(i);
        Dimension d = comp.getPreferredSize();
        d.width = (int) (sw * d.width);
        d.height = (int) (sh * d.height);
        if (w[c] < d.width) {
          w[c] = d.width;
        }
        if (h[r] < d.height) {
          h[r] = d.height;
        }
      }
      for (int c = 0, x = insets.left; c < ncols; c ++) {
        for (int r = 0, y = insets.top; r < nrows; r ++) {
          int i = r * ncols + c;
          if (i < ncomponents) {
            parent.getComponent(i).setBounds(x, y, w[c], h[r]);
          }
          y += h[r] + vgap;
        }
        x += w[c] + hgap;
      }
    }
  }  
}

[SSCCE.java]

import java.awt.Color;
import javax.swing.*;
import javax.swing.border.*;

public class SSCCE extends JFrame{

    JPanel innerPane = new JPanel();
    JScrollPane scr  = new JScrollPane(innerPane);

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


    public SSCCE() {

        setSize(400, 800);
        innerPane.setLayout(new GridLayout2(0, 1));

        add(scr);

        for (int i = 0; i < 30; i++)
        {
            innerPane.add(getPane());
        }

        setVisible(true);

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {}

        for (int i = 0; i < 30; i++)
        {
            if (i%2==0)
                innerPane.getComponent(i).setVisible(false);
        }

    }


    private JPanel getPane()
    {
        JPanel ret = new JPanel();
        JLabel lbl = new JLabel("This is a pane.");

        ret.add(lbl);
        ret.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
        ret.setBackground(Color.gray);

        return ret;

    }

}

推荐答案


因为组件之间仍然存在空隙。

because there is still an empty gap where the components were.

是的,GridLayout并不那么聪明。它只使用组件总数来确定行/列的数量。

Yes, GridLayout is not that smart. It just uses the total number of components to determine the number of row/columns.


有没有快速简便的方法呢?

Is there a quick and easy way to do this?

我会创建一个自定义布局管理器。只需复制GridLayout代码并进行一些更改。基本更改将是:

I would create a custom layout manager. Just copy the GridLayout code and make a couple of changes. The basic changes would be:


  1. 覆盖 ncomponents 变量。您不需要仅使用面板上的组件数量,而是需要遍历所有组件并计算可见组件。

  1. Override the ncomponents variable. Instead of just using the number of components on the panel you would need to loop thorugh all the components and count the visible ones.

在布局代码中,您将需要添加 if(可见)检查。

In the layout code you would need to add an if (visible) check.

编辑:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class InvisibleGridLayout implements LayoutManager, java.io.Serializable
{
    int hgap;
    int vgap;
    int rows;
    int cols;

    public InvisibleGridLayout() {
    this(1, 0, 0, 0);
    }

    public InvisibleGridLayout(int rows, int cols) {
    this(rows, cols, 0, 0);
    }

    public InvisibleGridLayout(int rows, int cols, int hgap, int vgap) {
    if ((rows == 0) && (cols == 0)) {
        throw new IllegalArgumentException("rows and cols cannot both be zero");
    }
    this.rows = rows;
    this.cols = cols;
    this.hgap = hgap;
    this.vgap = vgap;
    }

    public int getRows() {
    return rows;
    }

    public void setRows(int rows) {
    if ((rows == 0) && (this.cols == 0)) {
        throw new IllegalArgumentException("rows and cols cannot both be zero");
    }
    this.rows = rows;
    }

    public int getColumns() {
    return cols;
    }

    public void setColumns(int cols) {
    if ((cols == 0) && (this.rows == 0)) {
        throw new IllegalArgumentException("rows and cols cannot both be zero");
    }
    this.cols = cols;
    }

    public int getHgap() {
    return hgap;
    }

    public void setHgap(int hgap) {
    this.hgap = hgap;
    }

    public int getVgap() {
    return vgap;
    }

    public void setVgap(int vgap) {
    this.vgap = vgap;
    }

    public void addLayoutComponent(String name, Component comp) {
    }

    public void removeLayoutComponent(Component comp) {
    }

    public Dimension preferredLayoutSize(Container parent) {
      synchronized (parent.getTreeLock()) {
    Insets insets = parent.getInsets();
//  int ncomponents = parent.getComponentCount();
    int ncomponents = getVisibleComponents(parent);
    int nrows = rows;
    int ncols = cols;

    if (nrows > 0) {
        ncols = (ncomponents + nrows - 1) / nrows;
    } else {
        nrows = (ncomponents + ncols - 1) / ncols;
    }
    int w = 0;
    int h = 0;
//  for (int i = 0 ; i < ncomponents ; i++) {
    for (int i = 0 ; i < parent.getComponentCount(); i++) {
        Component comp = parent.getComponent(i);

        if (!comp.isVisible()) continue; // added

        Dimension d = comp.getPreferredSize();
        if (w < d.width) {
        w = d.width;
        }
        if (h < d.height) {
        h = d.height;
        }
    }

    Dimension d = new Dimension(insets.left + insets.right + ncols*w + (ncols-1)*hgap,
                 insets.top + insets.bottom + nrows*h + (nrows-1)*vgap);

    return d;
      }
    }

    public Dimension minimumLayoutSize(Container parent) {
      synchronized (parent.getTreeLock()) {
        Insets insets = parent.getInsets();
//  int ncomponents = parent.getComponentCount();
    int ncomponents = getVisibleComponents(parent);
    int nrows = rows;
    int ncols = cols;

    if (nrows > 0) {
        ncols = (ncomponents + nrows - 1) / nrows;
    } else {
        nrows = (ncomponents + ncols - 1) / ncols;
    }
    int w = 0;
    int h = 0;
//  for (int i = 0 ; i < ncomponents ; i++) {
    for (int i = 0 ; i < parent.getComponentCount(); i++) {
        Component comp = parent.getComponent(i);

        if (!comp.isVisible()) continue; // added

        Dimension d = comp.getMinimumSize();
        if (w < d.width) {
        w = d.width;
        }
        if (h < d.height) {
        h = d.height;
        }
    }

    Dimension d = new Dimension(insets.left + insets.right + ncols*w + (ncols-1)*hgap,
                 insets.top + insets.bottom + nrows*h + (nrows-1)*vgap);

    return d;
      }
    }

    public void layoutContainer(Container parent) {
      synchronized (parent.getTreeLock()) {
    Insets insets = parent.getInsets();
//  int ncomponents = parent.getComponentCount();
    int ncomponents = getVisibleComponents(parent);
    int nrows = rows;
    int ncols = cols;
    boolean ltr = parent.getComponentOrientation().isLeftToRight();

    if (ncomponents == 0) {
        return;
    }
    if (nrows > 0) {
        ncols = (ncomponents + nrows - 1) / nrows;
    } else {
        nrows = (ncomponents + ncols - 1) / ncols;
    }

//  int w = parent.width - (insets.left + insets.right);
//  int h = parent.height - (insets.top + insets.bottom);
    int w = parent.getSize().width - (insets.left + insets.right);
    int h = parent.getSize().height - (insets.top + insets.bottom);
    w = (w - (ncols - 1) * hgap) / ncols;
    h = (h - (nrows - 1) * vgap) / nrows;
/*
    if (ltr) {
        for (int c = 0, x = insets.left ; c < ncols ; c++, x += w + hgap) {
        for (int r = 0, y = insets.top ; r < nrows ; r++, y += h + vgap) {
            int i = r * ncols + c;
            if (i < ncomponents) {
            parent.getComponent(i).setBounds(x, y, w, h);
            }
        }
        }
    } else {
//      for (int c = 0, x = parent.width - insets.right - w; c < ncols ; c++, x -= w + hgap) {
        for (int c = 0, x = parent.getSize().width - insets.right - w; c < ncols ; c++, x -= w + hgap) {
        for (int r = 0, y = insets.top ; r < nrows ; r++, y += h + vgap) {
            int i = r * ncols + c;
            if (i < ncomponents) {
            parent.getComponent(i).setBounds(x, y, w, h);
            }
        }
        }
    }
      }
*/

        int i = 0;

        if (ltr)
        {
            for (int r = 0, y = insets.top ; r < nrows ; r++, y += h + vgap)
            {
                int c = 0;
                int x = insets.left;

                while (c < ncols)
                {
                    if (i >= parent.getComponentCount()) break;

                    Component component = parent.getComponent(i);

                    if (component.isVisible())
                    {
                        parent.getComponent(i).setBounds(x, y, w, h);
                        c++;
                        x += w + hgap;
                    }

                    i++;
                }
            }
        }

    }}

    private int getVisibleComponents(Container parent)
    {
        int visible = 0;

        for (Component c: parent.getComponents())
        {
            if (c.isVisible())
                visible++;
        }

        return visible;
    }

    public String toString() {
    return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap +
                           ",rows=" + rows + ",cols=" + cols + "]";
    }



    public static void main(String[] args)
    {
        final JPanel innerPane = new JPanel();
        JScrollPane scr  = new JScrollPane(innerPane);

        innerPane.setLayout(new InvisibleGridLayout(0, 3));


        for (int i = 0; i < 30; i++)
        {
            JPanel ret = new JPanel();
            JLabel lbl = new JLabel("This is  pane " + i);

            ret.add(lbl);
            ret.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
            ret.setBackground(Color.gray);

            innerPane.add(ret);
        }

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(scr);
        frame.setBounds(400, 0, 400, 700);
        frame.setVisible(true);

        javax.swing.Timer timer = new javax.swing.Timer(2000, new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                for (int i = 0; i < 30; i++)
                {
                    if (i%2==0)
                        innerPane.getComponent(i).setVisible(false);
                }

            }
        });
        timer.setRepeats(false);
        timer.start();

    }
}

这篇关于不可见的组件仍然占用空间JPanel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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