Java 在JFrame窗口外部单击时自动关闭该窗口

Java 在JFrame窗口外部单击时自动关闭该窗口,java,swing,jframe,Java,Swing,Jframe,我这里有一个相当基本的JFrame,我想在用户点击窗口外部时自动关闭窗口。当用户在窗口外单击时(通过某种方式检测到窗口外的单击),是否可以关闭窗口 检测帧外的点击是困难的,因为它可能是对java无法访问的任何其他应用程序的点击 您可以尝试使用FocusListener,如下所示 import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.WindowConstants; import java.awt.even

我这里有一个相当基本的JFrame,我想在用户点击窗口外部时自动关闭窗口。当用户在窗口外单击时(通过某种方式检测到窗口外的单击),是否可以关闭窗口


检测帧外的点击是困难的,因为它可能是对java无法访问的任何其他应用程序的点击

您可以尝试使用
FocusListener
,如下所示

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

public class AutoCloseFrameDemo {
  public static void main( String[] args ) {
    final JFrame frame = new JFrame( "Test" );
    frame.addFocusListener( new FocusListener() {
      private boolean gained = false;
      @Override
      public void focusGained( FocusEvent e ) {
        gained = true;
      }

      @Override
      public void focusLost( FocusEvent e ) {
        if ( gained ){
          frame.dispose();
        }
      }
    } );
    frame.add( new JLabel( "testlabel" ) );

    frame.pack();
    frame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE );
    frame.setVisible( true );
  }
}
这适用于这个简单的用例。还不确定如果在框架中放置一个
JTextField
,文本字段获得焦点,会发生什么。如果这也导致
JFrame
失去焦点,那么您的应用程序将毫无用处

编辑

更可靠的解决方案可能是将侦听器连接到
KeyboardFocusManager

import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
import java.awt.BorderLayout;
import java.awt.KeyboardFocusManager;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;

public class AutoCloseFrameDemo {
  public static void main( String[] args ) {
    final JFrame frame = new JFrame( "Test" );

    KeyboardFocusManager.getCurrentKeyboardFocusManager().
        addVetoableChangeListener( "focusedWindow",
                                   new VetoableChangeListener() {
                                     private boolean gained = false;

                                     @Override
                                     public void vetoableChange( PropertyChangeEvent evt ) throws PropertyVetoException {
                                       if ( evt.getNewValue() == frame ) {
                                         gained = true;
                                       }
                                       if ( gained && evt.getNewValue() != frame ) {
                                         frame.dispose();
                                       }
                                     }
                                   } );

    frame.add( new JTextField( 10 ), BorderLayout.NORTH );
    frame.add( new JTextField( 10 ), BorderLayout.SOUTH );

    frame.pack();
    frame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE );
    frame.setVisible( true );
  }
}

这允许在帧中的不同文本字段之间切换焦点。

我希望这与我的问题相关:实际上,该问题包含您需要的确切答案…这在所有情况下都不起作用,但一旦失去焦点,您可以关闭帧。一旦检测到失去焦点,关闭窗口很容易。在JFrame窗口外单击时自动关闭它。我可以问一下为什么吗?这不是一个非常用户友好的设计。您可以使用WindowListener#windowDeactivated或WindowFocusListener#windowLostFocus@MadProgrammer是的,我支持这一点,但你必须小心使用自己的JDialog(因为你无论如何都必须使用FocusListener)。
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
import java.awt.BorderLayout;
import java.awt.KeyboardFocusManager;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;

public class AutoCloseFrameDemo {
  public static void main( String[] args ) {
    final JFrame frame = new JFrame( "Test" );

    KeyboardFocusManager.getCurrentKeyboardFocusManager().
        addVetoableChangeListener( "focusedWindow",
                                   new VetoableChangeListener() {
                                     private boolean gained = false;

                                     @Override
                                     public void vetoableChange( PropertyChangeEvent evt ) throws PropertyVetoException {
                                       if ( evt.getNewValue() == frame ) {
                                         gained = true;
                                       }
                                       if ( gained && evt.getNewValue() != frame ) {
                                         frame.dispose();
                                       }
                                     }
                                   } );

    frame.add( new JTextField( 10 ), BorderLayout.NORTH );
    frame.add( new JTextField( 10 ), BorderLayout.SOUTH );

    frame.pack();
    frame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE );
    frame.setVisible( true );
  }
}