java - 使用 addWindowListener 的困难
问题描述
我正在尝试实现一个侦听器来检测窗口的关闭。我的主类正在扩展其他类,因此我无法扩展不允许我使用 addWindowListener 的 JFrame。
我已经尝试了下面的代码,但它不起作用。
public class PowerPanel extends AnotherPanel implements ActionListener, PropertyChangeListener {
// logic …
this.addWindowListener(new WindowAdapter() {
public void windowClosing (WindowEvent e ) {
// do things
}
});
}
我得到的错误表明 addWindowListener 是“未定义类型 PowerPanel”。
解决方案
您不能将窗口侦听器添加到面板中 - 您需要将其添加到java.awt.Window
实例中,在您的情况下是JFrame
.
如果您很难将JFrame
实例传递到面板中 - 您可以通过不同的方式访问它:
public class SamplePanel extends JPanel
{
/**
* Simple panel example that has no idea about it's parent window.
*/
public SamplePanel ()
{
super ();
// Your custom window listener
final WindowAdapter windowAdapter = new WindowAdapter ()
{
@Override
public void windowClosing ( final WindowEvent e )
{
System.out.println ( "Window is closing" );
}
};
// Ancestor availability listener
// It will make sure that whenever component appears on some visible window
// and is displayable container - we will add our window listener to it
addAncestorListener ( new AncestorAdapter ()
{
/**
* Saved window to remove listener from later on.
*/
private Window window = null;
@Override
public void ancestorAdded ( final AncestorEvent event )
{
// Component appeared on some window, we can add our listener now
addListener ();
}
@Override
public void ancestorMoved ( final AncestorEvent event )
{
// Re-adding listener to potentially new parent window
removeListener ();
addListener ();
}
@Override
public void ancestorRemoved ( final AncestorEvent event )
{
// Component was hidden or removed, we need to remove our listener
removeListener ();
}
/**
* Adds window listener.
*/
protected void addListener ()
{
window = SwingUtilities.getWindowAncestor ( SamplePanel.this );
if ( window != null )
{
window.addWindowListener ( windowAdapter );
}
}
/**
* Removes window listener.
*/
protected void removeListener ()
{
if ( window != null )
{
window.removeWindowListener ( windowAdapter );
window = null;
}
}
} );
}
/**
* Sample main method for runing the example.
*
* @param args arguments
*/
public static void main ( final String[] args )
{
SwingUtilities.invokeLater ( new Runnable ()
{
@Override
public void run ()
{
final JFrame frame = new JFrame ();
final SamplePanel panel = new SamplePanel ();
panel.add ( new JLabel ( "Sample panel content" ) );
frame.add ( panel );
frame.pack ();
frame.setDefaultCloseOperation ( JFrame.DISPOSE_ON_CLOSE );
frame.setLocationRelativeTo ( null );
frame.setVisible ( true );
}
} );
}
}
使用此代码,您的面板将在显示时自动在其父窗口上注册窗口侦听器。一旦面板被隐藏或从窗口中删除,它也会自动删除侦听器,因此这可能是您可以拥有的最佳解决方案。
但要小心,如果您将在同一个窗口上多次使用该面板 - 所有实例都将添加自己的侦听器,并且都将分别执行关闭操作。如果您只想在每个窗口/框架/对话框实例中执行一次关闭操作 - 您需要在窗口本身上添加侦听器,最好是在创建它的位置以免使其模糊。
您可能还会注意到,在我的示例中,实际上有一个方法可以直接检索面板的父窗口:
window = SwingUtilities.getWindowAncestor ( SamplePanel.this );
尽管您不能直接在面板中使用它,因为在创建面板的那一刻,它还没有添加到任何容器中,更不用说可见窗口了。这就是为什么需要我展示的带有祖先侦听器的解决方案的原因。
推荐阅读
- javascript - 使用 jquery 在 HTML 表中追加行不起作用
- node.js - 减少 MongoDB 延迟
- user-interface - Godot如何使标签上的文本居中?
- python - 使用 Apache Beam(并行)查找组件?
- firebase - 对帖子发表评论的 Firebase 规则
- jquery - FullCalendar:如何创建自定义时间段?
- vue.js - 使用 vee-validate 验证 Dropbox
- jenkins - 如何根据前一阶段的输出在 Jenkins 中运行条件以失败
- java - 为什么变量更改不持久化方法调用?
- scala - Spark Dataframe - 获取所有对列表(Scala)