我当前正在开发一个Java Swing应用程序,该应用程序使用提供的here的TableLayout布局管理器包.
我使用TableLayout的方式是动态地从布局中动态添加和删除组件以及动态地添加和删除行.在启动应用程序并按照所需的方式运行后,我决定检查应用程序的内存使用情况,以查看在程序中执行操作时的外观.
我注意到,当我添加组件时,内存使用率会略有上升,但是当我删除它们时,内存不会回落.出于明显的原因,这令人震惊.因此,我打开了Java的JVisualVM,以了解交易情况.
我的UserPanel.java类的实例数量从0变为6,这是可以预期的,因为我已经将其中6个实例添加到表布局中.当我删除所有6个实例时,令我沮丧的是,所有6个实例仍在内存中.我发现该引用使6个项目保持活动状态,结果发现它们仍然停留在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);
}
问题最终导致当将组件添加到表布局中时,该组件被包装到TableLayout子类“ Entry”的另一个对象中.
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());
}
入门内部舱位:
// 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是第三方,因此并不奇怪.如果有人可以将我与其他问题相关联的答案或任何形式的信息,对我来说将是有益的.
谢谢.
解决方法:
简短答案
没错,removeLayoutComponent()方法无法正常工作.
更长的答案
尽管Oracle上的TableLayout article没有日期,但2004年11月与TableLayout作者Daniel Barbalace的interview年在一起表明,Oracle(Sun)文章可能来自2001年左右.
采访中还提到了TableLayout的更新,尽管不幸的是,它没有任何迹象表明可能有更新可用.
经过一番搜索,我偶然发现了一个驻留在java.net上的TableLayout项目.该项目归“ Clearthought Software” 1所有,并已将tableLayout重新打包在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;
}
可在以下svn存储库中找到TableLayout的更新代码:https://svn.java.net/svn/tablelayout~svn
> www.clearthought.info的whois显示注册人为Daniel Barbalace.