不可见的组件仍然占用空间JPanel [英] Invisible components still take up space 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:
-
覆盖
ncomponents
变量。您不需要仅使用面板上的组件数量,而是需要遍历所有组件并计算可见组件。
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屋!