定义窗口关闭事件

这篇博客介绍了如何使用Java AWT库创建一个Frame窗口,并添加一个Panel面板。通过设置布局为null,可以自定义Panel的位置和大小。此外,还展示了如何设置背景颜色,并添加了一个窗口监听器来响应窗口关闭事件,当用户尝试关闭窗口时,程序会退出。
package StudyGUI;
//Panel面板和事件监听事件

import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class StudyPanel {
    public static void main(String[] args) {
        Frame frame =  new Frame();
        Panel panel = new Panel();
        //设置布局
        frame.setLayout(null);
        //坐标
        panel.setBounds(50,50,300,300);
        panel.setBackground(Color.black);
        //颜色可以自定义颜色类
        //panel.setBackground(new Color(55,66,77));
        //将panel面板添加到窗口frame中
        frame.add (panel);
        frame.setBackground(Color.blue);
        frame.setSize(500,500);
        frame.setVisible(true);//设置窗体可见
        //定义监听事件关闭窗口
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

    }
}

<think>在WPF中,我们可以通过重写窗口的OnClosing方法或者订阅Closing事件定义窗口关闭时的逻辑。这样可以在窗口关闭前执行一些清理操作,比如释放资源、保存数据等。 下面给出两种方式的示例代码: ### 方式1:重写OnClosing方法 这种方法适用于自定义窗口类,通过继承Window类并重写OnClosing方法。 ```csharp using System.Windows; using System.ComponentModel; public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } // 重写OnClosing方法 protected override void OnClosing(CancelEventArgs e) { // 在这里添加关闭窗口前的处理逻辑 // 例如:询问用户是否确认关闭 MessageBoxResult result = MessageBox.Show("确定要关闭窗口吗?", "确认关闭", MessageBoxButton.YesNo, MessageBoxImage.Question); if (result == MessageBoxResult.No) { // 取消关闭 e.Cancel = true; } else { // 执行清理操作,例如释放资源 // ... // 调用基类方法 base.OnClosing(e); } } } ``` ### 方式2:订阅Closing事件 这种方法适用于任何窗口,无需继承,直接在窗口的构造函数或其他地方订阅Closing事件。 ```csharp using System.Windows; using System.ComponentModel; public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); // 订阅Closing事件 this.Closing += MainWindow_Closing; } private void MainWindow_Closing(object sender, CancelEventArgs e) { // 在这里添加关闭窗口前的处理逻辑 // 例如:询问用户是否确认关闭 MessageBoxResult result = MessageBox.Show("确定要关闭窗口吗?", "确认关闭", MessageBoxButton.YesNo, MessageBoxImage.Question); if (result == MessageBoxResult.No) { // 取消关闭 e.Cancel = true; } else { // 执行清理操作,例如释放资源 // ... } } } ``` ### 代码说明 1. **CancelEventArgs**: - 该事件参数有一个`Cancel`属性,将其设置为`true`可以取消窗口关闭操作。 2. **资源释放**: - 在窗口关闭时,应当释放非托管资源(如文件句柄、数据库连接、网络连接等)。 - 对于托管资源,通常不需要手动释放,垃圾回收器会自动处理。但如果资源实现了`IDisposable`接口,建议在此时调用`Dispose()`方法。 3. **注意事项**: - 在关闭逻辑中避免执行耗时操作,否则会影响用户体验。 - 如果关闭操作需要用户确认,务必提供取消关闭的选项(即设置`e.Cancel=true`)。 ### 示例:在关闭时保存数据 ```csharp protected override void OnClosing(CancelEventArgs e) { // 检查数据是否已保存 if (!DataSaved) { var result = MessageBox.Show("数据未保存,是否保存并关闭?", "保存数据", MessageBoxButton.YesNoCancel, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) { SaveData(); // 保存数据 } else if (result == MessageBoxResult.No) { // 不保存,直接关闭 } else { e.Cancel = true; // 取消关闭 return; } } // 释放资源 ReleaseResources(); base.OnClosing(e); } private void SaveData() { // 保存数据逻辑 } private void ReleaseResources() { // 释放资源逻辑 } ``` ### 最佳实践 - 对于非托管资源,建议实现`IDisposable`接口,并在窗口的Closing事件或OnClosing方法中调用`Dispose()`。 - 避免在关闭事件中抛出异常,否则可能导致资源泄露。 --- §§相关问题§§: 1. 如何在WPF中实现窗口关闭时的数据保存确认? 2. 在WPF中,窗口的Closing事件和Closed事件有什么区别? 3. 如何防止WPF窗口被用户误关闭? 4. 在多窗口应用中,如何确保主窗口关闭时所有子窗口都被正确关闭? </think># WPF 窗口关闭函数的定义与实现 在 WPF 中,定义窗口关闭函数主要有两种方式:重写 `OnClosed` 方法或订阅 `Closed` 事件。下面我将详细解释这两种方法并提供完整示例代码。 ## 方法 1:重写 OnClosed 方法(推荐) ```csharp using System.Windows; public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } // 重写窗口关闭方法 protected override void OnClosed(EventArgs e) { // 执行清理操作 ReleaseResources(); // 可选:记录关闭日志 LogWindowClosure(); // 调用基类方法完成关闭过程 base.OnClosed(e); // 可选:关闭整个应用程序 // Application.Current.Shutdown(); } private void ReleaseResources() { // 释放文件句柄、数据库连接等资源 if (fileStream != null) { fileStream.Dispose(); fileStream = null; } // 释放其他托管资源 disposableResource?.Dispose(); // 释放非托管资源 if (nativeResource != IntPtr.Zero) { NativeMethods.FreeResource(nativeResource); nativeResource = IntPtr.Zero; } } private void LogWindowClosure() { // 记录窗口关闭事件 Logger.Log($"窗口 {Title} 于 {DateTime.Now} 关闭"); } } ``` ### 代码说明 1. **`OnClosed` 方法**: - 在窗口完全关闭后触发 - 是窗口生命周期的一部分 - 适用于需要确保执行的清理操作 2. **资源释放**: - 文件流、数据库连接等应在关闭时释放 - 使用 `Dispose()` 方法释放实现了 `IDisposable` 的对象 - 对于非托管资源,需要显式释放 3. **日志记录**: - 记录窗口关闭时间和其他有用信息 - 便于调试和审计 ## 方法 2:订阅 Closed 事件 ```csharp using System.Windows; public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); // 订阅窗口关闭事件 this.Closed += MainWindow_Closed; } private void MainWindow_Closed(object sender, EventArgs e) { // 执行清理操作 ReleaseResources(); // 可选:记录关闭日志 LogWindowClosure(); } // ReleaseResources 和 LogWindowClosure 方法与上面相同 } ``` ## 完整的窗口关闭处理示例 ```csharp using System; using System.ComponentModel; using System.IO; using System.Windows; using System.Windows.Threading; public partial class MainWindow : Window, INotifyPropertyChanged { private FileStream _logFileStream; private DispatcherTimer _timer; public MainWindow() { InitializeComponent(); DataContext = this; // 初始化资源 InitializeResources(); // 订阅关闭事件(两种方式任选其一) this.Closed += MainWindow_Closed; // 或者重写 OnClosed 方法 } private void InitializeResources() { // 创建日志文件 _logFileStream = new FileStream("app_log.txt", FileMode.Append, FileAccess.Write); // 创建定时器 _timer = new DispatcherTimer(); _timer.Interval = TimeSpan.FromSeconds(1); _timer.Tick += Timer_Tick; _timer.Start(); } private void Timer_Tick(object sender, EventArgs e) { // 定时器操作 CurrentTime = DateTime.Now.ToString("HH:mm:ss"); } // 使用 INotifyPropertyChanged 更新 UI public string CurrentTime { get => _currentTime; set { _currentTime = value; OnPropertyChanged(nameof(CurrentTime)); } } private string _currentTime; public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } // 方法1:重写 OnClosed protected override void OnClosed(EventArgs e) { CleanupResources(); base.OnClosed(e); } // 方法2:事件处理程序 private void MainWindow_Closed(object sender, EventArgs e) { CleanupResources(); } private void CleanupResources() { // 停止并释放定时器 if (_timer != null) { _timer.Stop(); _timer.Tick -= Timer_Tick; _timer = null; } // 关闭日志文件 if (_logFileStream != null) { StreamWriter writer = new StreamWriter(_logFileStream); writer.WriteLine($"应用程序关闭时间: {DateTime.Now}"); writer.Flush(); _logFileStream.Close(); _logFileStream.Dispose(); _logFileStream = null; } // 保存应用程序设置 Properties.Settings.Default.Save(); } } ``` ## 处理窗口关闭前的确认 如果您需要在关闭前进行确认(例如保存未保存的更改),请使用 `Closing` 事件: ```csharp public MainWindow() { InitializeComponent(); // 订阅关闭事件 this.Closing += MainWindow_Closing; } private void MainWindow_Closing(object sender, CancelEventArgs e) { if (HasUnsavedChanges) { MessageBoxResult result = MessageBox.Show( "您有未保存的更改,确定要关闭吗?", "确认关闭", MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.No) { e.Cancel = true; // 取消关闭操作 } } } ``` ## 注意事项和最佳实践 1. **资源释放顺序**: - 先停止服务(如定时器、网络监听) - 然后保存数据 - 最后释放资源 2. **异常处理**: ```csharp private void CleanupResources() { try { // 清理代码 } catch (Exception ex) { // 记录异常但不要阻止关闭 Logger.Error("资源清理失败", ex); } } ``` 3. **多窗口应用**: - 主窗口关闭时应关闭所有子窗口 - 使用 `Application.Current.Windows` 遍历所有窗口 4. **MVVM 模式下的处理**: ```csharp // 在 ViewModel 中 public void OnWindowClosing(object sender, CancelEventArgs e) { if (HasUnsavedChanges && !ConfirmDiscardChanges()) { e.Cancel = true; } } // 在视图中 private void Window_Closing(object sender, CancelEventArgs e) { var vm = DataContext as MainViewModel; vm?.OnWindowClosing(sender, e); } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值