[英]Close current window using ctrl+w
我有一個使用一堆JFrame
對象的Java程序。 為了使清理桌面更加容易,我想實現可以使用Ctrl + w關閉當前的焦點窗口。
我試圖使用一個鍵綁定(在任何視圖的超類中),該鍵綁定的Action
的actionPerformed
方法包含以下內容:
frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
只要我只使用一個窗口,這就可以很好地工作。 它僅在最后打開的框架聚焦時起作用,並且僅關閉該框架。
我的問題是:
KeyListener
添加任何單個組件的情況下為每幀創建一個關鍵綁定。 為什么鍵綁定的行為是這樣的? (我想這是設計使然。)
我想您做錯了什么,但是如果沒有任何示例代碼,就不可能知道
如何在不將任何單個組件添加到KeyListener的情況下為每幀創建一個關鍵綁定
您可以使用多種方法來實現此目標...
一種方法是采用“全局”方法,該系統不依賴於您從根解決方案擴展而來的系統,而該系統幾乎可以應用於任何現有或將來的項目。
AWTEventListener
一種解決方案可能是將AWTEventListener
附加到Toolkit
。 這是一個很低的級別,可讓您訪問系統正在處理的所有關鍵事件
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.AWTEventListener;
import java.awt.event.KeyEvent;
import javax.swing.FocusManager;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
private int count = 0;
private int xPos = 10;
private int yPos = 10;
public Test() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
installKeyboardMonitor();
for (int index = 0; index < 10; index++) {
makeWindow();
}
}
});
}
public static void installKeyboardMonitor() {
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent event) {
KeyEvent ke = (KeyEvent) event;
if (ke.getID() == KeyEvent.KEY_PRESSED) {
System.out.println("Pressed");
if (ke.getKeyCode() == KeyEvent.VK_W) {
System.out.println("W Key");
if (ke.isControlDown()) {
System.out.println("Control down");
Window window = FocusManager.getCurrentManager().getActiveWindow();
if (window != null) {
window.dispose();
}
}
}
}
}
}, AWTEvent.KEY_EVENT_MASK);
}
public void makeWindow() {
count++;
JFrame frame = new JFrame("Test " + count);
frame.setContentPane(new JPanel(new BorderLayout()) {
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
});
frame.add(new JLabel("Window " + count));
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
frame.setLocation(xPos, yPos);
frame.setVisible(true);
xPos += 100;
yPos += 100;
}
}
KeyEventDispatcher
與AWTEventListener
,它的底層級別稍低一些,但它只專注於KeyEvent
,這使它易於管理,但是本質上是相同的
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.Window;
import java.awt.event.KeyEvent;
import javax.swing.FocusManager;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
private int count = 0;
private int xPos = 10;
private int yPos = 10;
public Test() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
installKeyboardMonitor();
for (int index = 0; index < 10; index++) {
makeWindow();
}
}
});
}
public static void installKeyboardMonitor() {
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
@Override
public boolean dispatchKeyEvent(KeyEvent ke) {
if (ke.getID() == KeyEvent.KEY_PRESSED) {
System.out.println("Pressed");
if (ke.getKeyCode() == KeyEvent.VK_W) {
System.out.println("W Key");
if (ke.isControlDown()) {
System.out.println("Control down");
Window window = FocusManager.getCurrentManager().getActiveWindow();
if (window != null) {
window.dispose();
return true;
}
}
}
}
return false;
}
});
}
public void makeWindow() {
count++;
JFrame frame = new JFrame("Test " + count);
frame.setContentPane(new JPanel(new BorderLayout()) {
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
});
frame.add(new JLabel("Window " + count));
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
frame.setLocation(xPos, yPos);
frame.setVisible(true);
xPos += 100;
yPos += 100;
}
}
另一解決方案是提供基於“配置”的解決方案。 這類似於具有基本組件的概念,但是使您不必再被鎖定在單個擴展點中。
這種方法比較麻煩,因為您實際上需要記住將其應用於應用程序可能創建的每個窗口和對話框。
它只是使用Key Bindings API來注冊與Windows JRootPane
的綁定,但是您幾乎可以使用任何您知道不會從窗口中刪除的組件。
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
private int count = 0;
private int xPos = 10;
private int yPos = 10;
public Test() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
for (int index = 0; index < 10; index++) {
makeWindow();
}
}
});
}
public static void installKeyBindings(JComponent component) {
InputMap inputMap = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = component.getActionMap();
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, KeyEvent.CTRL_DOWN_MASK), "Window.close");
actionMap.put("Window.close", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
Window window = SwingUtilities.windowForComponent(component);
if (window != null) {
window.dispose();
}
}
});
}
public void makeWindow() {
count++;
JFrame frame = new JFrame("Test " + count);
installKeyBindings(frame.getRootPane());
frame.setContentPane(new JPanel(new BorderLayout()) {
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
});
frame.add(new JLabel("Window " + count));
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
frame.setLocation(xPos, yPos);
frame.setVisible(true);
xPos += 100;
yPos += 100;
}
}
這只是三種可能的解決方案。 圍繞每個解決方案提供可配置性更高的解決方案並不需要花費太多精力(因此您可以提供按鍵),但是我將由您自己決定。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.