java - JDialog 关闭后留在 Swings 组件树中
问题描述
我有一个对话框视图,它使用 PropertyListener 将事件传播给调用者。我们使用 swing 组件内置的 PropertyListeners。现在,我们打开这些对话框之一,然后用户通过系统中的“X”按钮将其关闭。稍后我们调用以下代码段:
for ( final Window frame : Frame.getFrames() )
{
updateAllUIs( frame );
}
private static void updateAllUIs( final Window frame )
{
for ( final Window childWindow : frame.getOwnedWindows() )
{
updateAllUIs( childWindow );
}
SwingUtilities.updateComponentTreeUI( frame );
}
显然,这甚至可以到达早已关闭的对话框。是否dispose
被调用也没有区别。是否有一种可靠的方法来确保 Swing 不再包含对不再使用的对话框的任何内部引用?虽然我们应该清除我们的听众,但这仍然不应该发生。或者我在这里误解了什么?
重现问题的最小示例:
package dialogleak;
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.Window;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class DialogLeak
{
public static void main( String[] args )
{
JFrame mainFrame = new JFrame();
JButton dialogButton = new JButton( "Dialog" );
dialogButton.addActionListener( __ ->
{
JDialog dialog = new JDialog( mainFrame );
dialog.setModal( true );
dialog.add( new JTextField( "Hello world" ) );
dialog.getRootPane().addPropertyChangeListener( new PropertyChangeListener()
{
@Override
public void propertyChange( PropertyChangeEvent evt )
{
//Shouldn't be visible when dialog is invisible.
System.out.println( "Fired: " + evt.getPropertyName() + "; Dialog visible: " + dialog.isVisible() );
}
} );
dialog.setSize( 200, 100 );
dialog.setLocationRelativeTo( mainFrame );
//Doesn't make a difference, feel free to try.
//dialog.setDefaultCloseOperation( JDialog.DISPOSE_ON_CLOSE );
dialog.setVisible( true );
} );
JButton updateUIButton = new JButton( "Update UI" );
updateUIButton.addActionListener( __ ->
{
for ( Frame frame : Frame.getFrames() )
{
updateUIRecursively( frame );
}
} );
JPanel panel = new JPanel( new BorderLayout() );
mainFrame.add( panel );
panel.add( dialogButton, BorderLayout.NORTH );
panel.add( updateUIButton, BorderLayout.SOUTH );
mainFrame.setSize( 400, 300 );
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.setLocationRelativeTo( null );
mainFrame.setVisible( true );
}
private static void updateUIRecursively( Window window )
{
SwingUtilities.updateComponentTreeUI( window );
for ( final Window childWindow : window.getOwnedWindows() )
{
updateUIRecursively( childWindow );
}
}
}
解决方案
推荐阅读
- c - 重新分配分配的内存
- hive - SparkSQL 中的 Percentile 与 percentile_approx
- python - 在numpy数组中平滑具有粗糙边界的2D轮廓
- function - 你必须声明一个函数的类型吗?
- java - Mockito 中的 when() 是否使用严格参数验证调用?
- compiler-errors - 申请:不是程序;期望一个可以应用于参数的过程(方案)?
- db2 - 删除对没有约束名称的列的检查
- javascript - 从网络工作者获取数据后无法将数据设置到剪贴板
- c++ - 如何管理需要从递归仿函数/lambda 派生的模板参数的声明?
- python - 使用 Python 3 删除 MongoDB 中重复数据的方法