gpt4 book ai didi

java - 如何覆盖 JFrame 关闭 ('x' ) 按钮的默认监听器?

转载 作者:行者123 更新时间:2023-12-01 08:00:07 27 4
gpt4 key购买 nike

我想要 3 种退出应用程序的方法

  1. 击键 CTRL-Q
  2. 从菜单栏中选择“退出”
  3. 关闭 JFrame 上的“x”按钮

到目前为止,我所做的是为前两个添加偶数监听器,但我不知道如何让 JFrame 关闭“x”按钮来执行相同的操作。目前,它只是退出应用程序而不提示确认,因为它不知道如何进行确认。我基本上希望在用户确认他们想要退出后处理所有框架。前两种情况会发生这种情况,只是因为它们的操作监听器调用 exit() 方法来确认退出,然后继续处理所有帧。

public class MainWindow extends JFrame {
...
this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

this.addWindowListener(new WindowListener() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}

...

// this is part of the main menu bar (case #2)
JMenuItem mntmExit = new JMenuItem("Exit");
mntmExit.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent e) {
MainWindow.this.exit();
}

});

// this is case #1
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {

@Override
public boolean dispatchKeyEvent(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_Q && e.getModifiers() == InputEvent.CTRL_MASK) {
MainWindow.this.exit();
}

return false;
}

});
}

// the exit method
private void exit() {
int confirmed = JOptionPane.showConfirmDialog(this, "Are you sure you want to quit?", "Confirm quit", JOptionPane.YES_NO_OPTION);

if(confirmed == JOptionPane.YES_OPTION) {
Frame[] frames = Frame.getFrames();

for(Frame frame : frames) {
frame.dispose();
}
}
}

是否可以为关闭按钮分配一个 Action 监听器?如果没有,我还有其他方法可以解决这个问题吗?

最佳答案

将 JFrame 的默认关闭操作保留为 JFrame.DO_NOTHING_ON_CLOSE,但使用 WindowListener(或更简单地说,WindowAdapter)监听关闭尝试。

您可以对菜单项和按钮使用相同的 AbstractAction,然后在 WindowListener 中调用该操作的方法。例如

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.*;

public class ClosingJFrame {
public static void main(String[] args) {
final JFrame frame = new JFrame("My Frame");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

final CloseAction closeAction = new CloseAction(frame);

JPanel panel = new JPanel();
panel.add(new JButton(closeAction));

JMenuItem exitMenuItem = new JMenuItem(closeAction);
JMenu menu = new JMenu("File");
menu.setMnemonic(KeyEvent.VK_F);
menu.add(exitMenuItem);
JMenuBar menuBar = new JMenuBar();
menuBar.add(menu);

frame.setJMenuBar(menuBar);

frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
closeAction.confirmClosing();
}
});

frame.add(panel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);


}
}

class CloseAction extends AbstractAction {
private JFrame mainFrame;

public CloseAction(JFrame mainFrame) {
super("Exit");
putValue(MNEMONIC_KEY, KeyEvent.VK_X);
this.mainFrame = mainFrame;
}

@Override
public void actionPerformed(ActionEvent e) {
confirmClosing();
}

public void confirmClosing() {
int confirmed = JOptionPane.showConfirmDialog(mainFrame,
"Are you sure you want to quit?", "Confirm quit",
JOptionPane.YES_NO_OPTION);
if (confirmed == JOptionPane.YES_OPTION) {
// clean up code
System.exit(0);
}
}
}
<小时/>

编辑
哎呀,我忘了你的 ctrl-Q 击键位了。为此使用相同的操作,并使用 KeyBindings 将其绑定(bind)到 ctrl-q 键。改进后的代码:

import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.*;

public class ClosingJFrame {
public static void main(String[] args) {
final JFrame frame = new JFrame("My Frame");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

final CloseAction closeAction = new CloseAction(frame);

JPanel panel = new JPanel();
panel.add(new JButton(closeAction));

JMenuItem exitMenuItem = new JMenuItem(closeAction);
JMenu menu = new JMenu("File");
menu.setMnemonic(KeyEvent.VK_F);
menu.add(exitMenuItem);
JMenuBar menuBar = new JMenuBar();
menuBar.add(menu);

frame.setJMenuBar(menuBar);

frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
closeAction.confirmClosing();
}
});

// also use the same Action in your ctrl-q key bindings
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = panel.getInputMap(condition);
ActionMap actionMap = panel.getActionMap();
KeyStroke ctrlQKey = KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_DOWN_MASK);
inputMap.put(ctrlQKey, ctrlQKey.toString());
actionMap.put(ctrlQKey.toString(), closeAction);

frame.add(panel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);


}
}

class CloseAction extends AbstractAction {
private JFrame mainFrame;

public CloseAction(JFrame mainFrame) {
super("Exit");
putValue(MNEMONIC_KEY, KeyEvent.VK_X);
this.mainFrame = mainFrame;
}

@Override
public void actionPerformed(ActionEvent e) {
confirmClosing();
}

public void confirmClosing() {
int confirmed = JOptionPane.showConfirmDialog(mainFrame,
"Are you sure you want to quit?", "Confirm quit",
JOptionPane.YES_NO_OPTION);
if (confirmed == JOptionPane.YES_OPTION) {
// clean up code
System.exit(0);
}
}
}
<小时/>

编辑2
这句话让我担心:

then proceeds to dispose of all frames

因为这意味着您有多个 JFrame。如果是这样,您应该阅读此链接,因为它将解释为什么通常不需要这样做:The Use of Multiple JFrames, Good/Bad Practice?

<小时/>

编辑3
根据 Rob Camick 的评论:

You could also just set an accelerator for the CloseAction by doing something like:

putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("control Q")); 

Then the menu item will do the key bindings for you.

这将进入 CloseAction 的构造函数,如下所示:

   public CloseAction(JFrame mainFrame) {
super("Exit");
putValue(MNEMONIC_KEY, KeyEvent.VK_X);
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("control Q"));
this.mainFrame = mainFrame;
}

关于java - 如何覆盖 JFrame 关闭 ('x' ) 按钮的默认监听器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25952297/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com