Java Swing - TableLayout - 未从布局中删除的组件
Java Swing - TableLayout - Components Not Removing From Layout
我目前正在开发 Java Swing 应用程序,该应用程序利用 here 提供的 TableLayout 布局管理器包。
我使用 TableLayout 的方式是动态地在布局中动态添加和删除组件,以及动态添加和删除行。在我启动应用程序并按照我希望的方式 运行 之后,我决定检查应用程序的内存使用情况,以查看它在程序中执行操作时的情况。
我注意到,当我添加组件时,内存使用量会略有上升,但当我删除它们时,内存不会下降。出于显而易见的原因,这令人担忧。所以我打开了 java 的 JVisualVM 看看有什么问题。
我的 UserPanel.java class 的实例数从 0 变为 6,这是意料之中的,因为我已将其中的 6 个添加到 table 布局中。当我删除所有 6 个时,令我沮丧的是,所有 6 个实例仍在内存中。我找到了 reference keeping the 6 items alive 结果是它们仍然卡在 TableLayout 的组件列表中。
为了从父面板中删除组件,我使用了:
myJPanel.remove(userPanelInstance);
JPanel的remove方法调用方法
removeLayoutComponent(Component comp);
每个布局管理器都有(据我所知)。
TableLayout的removeLayoutComponent方法如下:
/** List of components and their sizes */
protected LinkedList list;
/**
* Removes the specified component from the layout.
*
* @param component component being removed
*/
public void removeLayoutComponent (Component component)
{
list.remove (component);
}
问题最终是,当一个组件被添加到 table 布局时,它被包装到 TableLayout subclass "Entry".[=18= 的另一个对象中]
public void addLayoutComponent (Component component, Object constraint)
{
if (constraint instanceof String)
{
// Create an entry to associate component with its constraints
constraint = new TableLayoutConstraints((String) constraint);
// Add component and constraints to the list
list.add (new Entry(component, (TableLayoutConstraints) constraint));
}
else if (constraint instanceof TableLayoutConstraints)
{
// Add component and constraints to the list
list.add (new Entry(component, (TableLayoutConstraints) constraint));
}
else if (constraint == null)
throw new IllegalArgumentException("No constraint for the component");
else
throw new IllegalArgumentException
("Cannot accept a constraint of class " + constraint.getClass());
}
条目内部Class:
// The following inner class is used to bind components to their constraints
protected class Entry extends TableLayoutConstraints
{
/** Component bound by the constraints */
protected Component component;
/** Does the component occupy a single cell */
protected boolean singleCell;
/**
* Constructs an Entry that binds a component to a set of constraints.
*
* @param component component being bound
* @param constranit constraints being applied
*/
public Entry (Component component, TableLayoutConstraints constraint)
{
super (constraint.col1, constraint.row1,
constraint.col2, constraint.row2,
constraint.hAlign, constraint.vAlign);
singleCell = ((row1 == row2) && (col1 == col2));
this.component = component;
}
/**
* Determines whether or not two entries are equal.
*
* @param object object being compared to; must be a Component if it
* is equal to this TableLayoutConstraints.
*
* @return True, if the entries refer to the same component object.
* False, otherwise.
*/
public boolean equals (Object object)
{
boolean equal = false;
if (object instanceof Component)
{
Component component = (Component) object;
equal = (this.component == component);
}
return equal;
}
}
因为每次添加新组件时都会将组件包装到此对象中,所以即使重写组件的equals()方法,removeLayoutComponent方法每次删除指定组件时都注定会失败。
为了使其正常工作并从内存中删除引用,我必须将 removeLayoutComponent 方法重写到此:
/* (non-Javadoc)
* @see layout.TableLayout#removeLayoutComponent(java.awt.Component)
*/
@Override
public void removeLayoutComponent(Component component)
{
for(int i = 0; i < list.size(); i++)
{
Entry compEntry = (Entry) list.get(i);
if(compEntry.equals(component))
{
list.remove(i);
break;
}
}
}
我的问题是,这是 TableLayout 布局管理器中的实际设计缺陷吗?或者我只是在做一些愚蠢的事情,没有根据 equals(Object other) 方法或其他方法正确使用 TableLayout 布局管理器?我错过了什么?
我尝试搜索与此相关的类似问题,但没有找到任何内容。由于 TableLayout 是第三方的,这并不奇怪。如果有人可以 link 我回答另一个问题并回答这个问题或任何类型的信息,那将对我有益。
谢谢。
TableLayout
最后更新于 2002 年 1 月 16 日,而我最喜欢的布局管理器 MigLayout
于 2017 年 2 月 16 日更新。这些信息足以让我们不使用 TableLayout
.
是的,这可能是一个错误。
MigLayout's
执行removeLayoutComponent()
:
@Override
public void removeLayoutComponent(Component comp)
{
synchronized(comp.getParent().getTreeLock()) {
scrConstrMap.remove(comp);
ccMap.remove(new SwingComponentWrapper(comp));
grid = null; // To clear references
}
}
总而言之,只需在您的项目中使用 MigLayout
或 GroupLayout
。
简答
你是对的,removeLayoutComponent()
方法不能正常工作。
更长的答案
虽然 TableLayout article on Oracle doesn't have a date, this November 2004 interview 与 TableLayout 作者 Daniel Barbalace 表明 Oracle (Sun) 文章可能来自 2001 年左右。
采访中还提到了 TableLayout 的更新,但不幸的是它没有给出任何可用更新的指示。
经过一番搜索,我偶然发现了一个托管在 java.net 上的 TableLayout 项目。此项目归 "Clearthought Software"1 所有,并在 info.clearthought.layout
.
下重新打包了 TableLayout
该版本中的 removeLayoutComponent()
实现与您建议的类似。
public void removeLayoutComponent (Component component)
{
// Remove the component
ListIterator iterator = list.listIterator(0);
while (iterator.hasNext())
{
Entry entry = (Entry) iterator.next();
if (entry.component == component)
iterator.remove();
}
// Indicate that the cell sizes are not known since
dirty = true;
}
TableLayout 的更新代码可以在这个 svn repo 中找到:https://svn.java.net/svn/tablelayout~svn
whois
for www.clearthought.info 显示注册人为 Daniel Barbalace。
我目前正在开发 Java Swing 应用程序,该应用程序利用 here 提供的 TableLayout 布局管理器包。
我使用 TableLayout 的方式是动态地在布局中动态添加和删除组件,以及动态添加和删除行。在我启动应用程序并按照我希望的方式 运行 之后,我决定检查应用程序的内存使用情况,以查看它在程序中执行操作时的情况。
我注意到,当我添加组件时,内存使用量会略有上升,但当我删除它们时,内存不会下降。出于显而易见的原因,这令人担忧。所以我打开了 java 的 JVisualVM 看看有什么问题。
我的 UserPanel.java class 的实例数从 0 变为 6,这是意料之中的,因为我已将其中的 6 个添加到 table 布局中。当我删除所有 6 个时,令我沮丧的是,所有 6 个实例仍在内存中。我找到了 reference keeping the 6 items alive 结果是它们仍然卡在 TableLayout 的组件列表中。
为了从父面板中删除组件,我使用了:
myJPanel.remove(userPanelInstance);
JPanel的remove方法调用方法
removeLayoutComponent(Component comp);
每个布局管理器都有(据我所知)。 TableLayout的removeLayoutComponent方法如下:
/** List of components and their sizes */
protected LinkedList list;
/**
* Removes the specified component from the layout.
*
* @param component component being removed
*/
public void removeLayoutComponent (Component component)
{
list.remove (component);
}
问题最终是,当一个组件被添加到 table 布局时,它被包装到 TableLayout subclass "Entry".[=18= 的另一个对象中]
public void addLayoutComponent (Component component, Object constraint)
{
if (constraint instanceof String)
{
// Create an entry to associate component with its constraints
constraint = new TableLayoutConstraints((String) constraint);
// Add component and constraints to the list
list.add (new Entry(component, (TableLayoutConstraints) constraint));
}
else if (constraint instanceof TableLayoutConstraints)
{
// Add component and constraints to the list
list.add (new Entry(component, (TableLayoutConstraints) constraint));
}
else if (constraint == null)
throw new IllegalArgumentException("No constraint for the component");
else
throw new IllegalArgumentException
("Cannot accept a constraint of class " + constraint.getClass());
}
条目内部Class:
// The following inner class is used to bind components to their constraints
protected class Entry extends TableLayoutConstraints
{
/** Component bound by the constraints */
protected Component component;
/** Does the component occupy a single cell */
protected boolean singleCell;
/**
* Constructs an Entry that binds a component to a set of constraints.
*
* @param component component being bound
* @param constranit constraints being applied
*/
public Entry (Component component, TableLayoutConstraints constraint)
{
super (constraint.col1, constraint.row1,
constraint.col2, constraint.row2,
constraint.hAlign, constraint.vAlign);
singleCell = ((row1 == row2) && (col1 == col2));
this.component = component;
}
/**
* Determines whether or not two entries are equal.
*
* @param object object being compared to; must be a Component if it
* is equal to this TableLayoutConstraints.
*
* @return True, if the entries refer to the same component object.
* False, otherwise.
*/
public boolean equals (Object object)
{
boolean equal = false;
if (object instanceof Component)
{
Component component = (Component) object;
equal = (this.component == component);
}
return equal;
}
}
因为每次添加新组件时都会将组件包装到此对象中,所以即使重写组件的equals()方法,removeLayoutComponent方法每次删除指定组件时都注定会失败。
为了使其正常工作并从内存中删除引用,我必须将 removeLayoutComponent 方法重写到此:
/* (non-Javadoc)
* @see layout.TableLayout#removeLayoutComponent(java.awt.Component)
*/
@Override
public void removeLayoutComponent(Component component)
{
for(int i = 0; i < list.size(); i++)
{
Entry compEntry = (Entry) list.get(i);
if(compEntry.equals(component))
{
list.remove(i);
break;
}
}
}
我的问题是,这是 TableLayout 布局管理器中的实际设计缺陷吗?或者我只是在做一些愚蠢的事情,没有根据 equals(Object other) 方法或其他方法正确使用 TableLayout 布局管理器?我错过了什么?
我尝试搜索与此相关的类似问题,但没有找到任何内容。由于 TableLayout 是第三方的,这并不奇怪。如果有人可以 link 我回答另一个问题并回答这个问题或任何类型的信息,那将对我有益。
谢谢。
TableLayout
最后更新于 2002 年 1 月 16 日,而我最喜欢的布局管理器 MigLayout
于 2017 年 2 月 16 日更新。这些信息足以让我们不使用 TableLayout
.
是的,这可能是一个错误。
MigLayout's
执行removeLayoutComponent()
:
@Override
public void removeLayoutComponent(Component comp)
{
synchronized(comp.getParent().getTreeLock()) {
scrConstrMap.remove(comp);
ccMap.remove(new SwingComponentWrapper(comp));
grid = null; // To clear references
}
}
总而言之,只需在您的项目中使用 MigLayout
或 GroupLayout
。
简答
你是对的,removeLayoutComponent()
方法不能正常工作。
更长的答案
虽然 TableLayout article on Oracle doesn't have a date, this November 2004 interview 与 TableLayout 作者 Daniel Barbalace 表明 Oracle (Sun) 文章可能来自 2001 年左右。
采访中还提到了 TableLayout 的更新,但不幸的是它没有给出任何可用更新的指示。
经过一番搜索,我偶然发现了一个托管在 java.net 上的 TableLayout 项目。此项目归 "Clearthought Software"1 所有,并在 info.clearthought.layout
.
该版本中的 removeLayoutComponent()
实现与您建议的类似。
public void removeLayoutComponent (Component component)
{
// Remove the component
ListIterator iterator = list.listIterator(0);
while (iterator.hasNext())
{
Entry entry = (Entry) iterator.next();
if (entry.component == component)
iterator.remove();
}
// Indicate that the cell sizes are not known since
dirty = true;
}
TableLayout 的更新代码可以在这个 svn repo 中找到:https://svn.java.net/svn/tablelayout~svn
whois
for www.clearthought.info 显示注册人为 Daniel Barbalace。