Java 单击其他位置时,如何隐藏Swing弹出窗口
我有一个弹出窗口,当用户点击按钮时显示。我想在发生以下任何事件时隐藏弹出窗口:Java 单击其他位置时,如何隐藏Swing弹出窗口,java,swing,popup,Java,Swing,Popup,我有一个弹出窗口,当用户点击按钮时显示。我想在发生以下任何事件时隐藏弹出窗口: 用户单击应用程序中的其他位置。(例如背景面板) 用户将应用程序最小化 JPOppMenu具有这种行为,但我需要的不仅仅是JMenuItems。以下代码块是演示当前用法的简化图示 import java.awt.*; import java.awt.event.ActionEvent; import javax.swing.*; public class PopupTester extends JFrame {
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class PopupTester extends JFrame {
public static void main(String[] args) {
final PopupTester popupTester = new PopupTester();
popupTester.setLayout(new FlowLayout());
popupTester.setSize(300, 100);
popupTester.add(new JButton("Click Me") {
@Override
protected void fireActionPerformed(ActionEvent event) {
Point location = getLocationOnScreen();
int y = (int) (location.getY() + getHeight());
int x = (int) location.getX();
JLabel myComponent = new JLabel("Howdy");
Popup popup = PopupFactory.getSharedInstance().getPopup(popupTester, myComponent, x, y);
popup.show();
}
});
popupTester.add(new JButton("No Click Me"));
popupTester.setVisible(true);
popupTester.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
当有人单击背景面板时,您可以添加到背景面板并隐藏弹出窗口
要对应用程序最小化做出反应,请使用附加到
等等,等等。可能看起来很乏味,但肯定会起作用。正如pajton在之前的评论中指出的那样,弹出窗口并不是一个听众可以轻松绑定的组件。但是,正如其文档所述,“Popup的实现负责创建和维护自己的组件,以便向用户呈现[其主题]。” 因此,在使用它作为表示机制时,您的弹出窗口必须以实际的Swing组件的形式显示。让它自己注册到该组件。当组件失去焦点时,将其自身隐藏
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.Popup;
public class PopupTester extends JFrame {
private static class MessagePopup extends Popup
implements WindowFocusListener
{
private final JDialog dialog;
public MessagePopup(Frame base, String message) {
super();
dialog = new JOptionPane().createDialog( base, "Message" );
dialog.setModal( false );
dialog.setContentPane( new JLabel( message ) );
}
@Override public void show() {
dialog.addWindowFocusListener( this );
dialog.setVisible( true );
}
@Override public void hide() {
dialog.setVisible( false );
dialog.removeWindowFocusListener( this );
}
public void windowGainedFocus( WindowEvent e ) {
// NO-OP
}
public void windowLostFocus( WindowEvent e ) {
hide();
}
}
public static void main(String[] args) {
final PopupTester popupTester = new PopupTester();
popupTester.setLayout(new FlowLayout());
popupTester.setSize(300, 100);
popupTester.add(new JButton("Click Me") {
@Override
protected void fireActionPerformed(ActionEvent event) {
Point location = getLocationOnScreen();
MessagePopup popup = new MessagePopup( popupTester, "Howdy" );
popup.show();
}
});
popupTester.add(new JButton("No Click Me"));
popupTester.setVisible(true);
popupTester.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
使用JPOppMenu。您可以向其添加任何组件,而不仅仅是菜单项。您可以向弹出窗口添加FocusListener,并在其失去焦点时进行处理。但是,当焦点丢失是由于其他应用程序引起时(新窗口出现在前台,您切换虚拟桌面等),这会给您带来一些麻烦
但是,也许您(a)知道这种情况不可能发生,或者(b)希望在这种情况下关闭弹出窗口。无论如何,基于焦点的方法可能仍然对您感兴趣。感谢pajton和Noel Ang为我指明了正确的方向!这是我最终得到的解决方案。我只是把它包括在这里,以便其他人可以从中受益 我最终选择了JWindow,因为它没有窗口装饰,但有焦点事件
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PopupTester extends JFrame {
private static class MessagePopup extends Popup implements WindowFocusListener {
private final JWindow dialog;
public MessagePopup(Frame base, JLabel component, int x, int y) {
super();
dialog = new JWindow(base);
dialog.setFocusable(true);
dialog.setLocation(x, y);
dialog.setContentPane(component);
component.setBorder(new JPopupMenu().getBorder());
dialog.setSize(component.getPreferredSize());
dialog.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
dialog.setVisible(false);
}
}
});
}
@Override
public void show() {
dialog.addWindowFocusListener(this);
dialog.setVisible(true);
}
@Override
public void hide() {
dialog.setVisible(false);
dialog.removeWindowFocusListener(this);
}
public void windowGainedFocus(WindowEvent e) {
// NO-OP
}
public void windowLostFocus(WindowEvent e) {
hide();
}
}
public static void main(String[] args) {
final PopupTester popupTester = new PopupTester();
popupTester.setLayout(new FlowLayout());
popupTester.setSize(300, 100);
popupTester.add(new JButton("Click Me") {
@Override
protected void fireActionPerformed(ActionEvent event) {
Point location = getLocationOnScreen();
int x = (int) location.getX();
int y = (int) (location.getY() + getHeight());
JLabel myComponent = new JLabel("Howdy");
MessagePopup popup = new MessagePopup(popupTester, myComponent, x, y);
popup.show();
}
});
popupTester.add(new JButton("No Click Me"));
popupTester.setVisible(true);
popupTester.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
我知道这是一个老问题,但我真的需要弹出在我的情况下工作。所以我尝试了一些方法,下面是我的解决方案 向添加到弹出窗口的组件添加
FocusListener
,并在该组件上编程focusLost
事件,以在焦点丢失时隐藏弹出窗口。显示弹出窗口后,在组件上调用requestFocus
方法
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import javax.swing.*;
public class PopupTester extends JFrame {
JButton myButton = new JButton("Click Me");
JLabel myComponent = new JLabel("Howdy");
Popup popup = null;
public PopupTester() {
setLayout(new FlowLayout());
setSize(300, 100);
add(myButton);
add(new JButton("No Click Me"));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myComponent.addFocusListener(new FocusAdapter() {
public void focusLost(FocusEvent e) {
if (popup != null) {
popup.hide();
}
}
});
myButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if (popup != null) {
popup.hide();
popup = null;
}
Point location = myButton.getLocationOnScreen();
int y = (int) (location.getY() + myButton.getHeight());
int x = (int) location.getX();
popup = PopupFactory.getSharedInstance().getPopup(PopupTester.this, myComponent, x, y);
popup.show();
myComponent.requestFocus();
}
});
}
public static void main(String[] args) {
PopupTester popupTester = new PopupTester();
popupTester.setVisible(true);
}
}
好建议。对于一个大的应用程序来说,这变得很困难,因为我不能在屏幕上的每个组件上都添加鼠标侦听器。遗憾的是,
弹出窗口
本身并不是JComponent
。然后,您可以附加一些侦听器来捕获失去焦点的事件。也许考虑使用<代码> jCalue,然后简单地>代码> MouseListener < /代码>及其<代码> MouthEXIT()/代码>方法.j对话框附带窗口装饰的行李。我能够模拟一些使用JWindow的东西,但是有大量的手动事件处理,结果仍然很奇怪。Popup真的从根本上被破坏了吗?它不能支持这样的东西吗?它扩展了对象
所以。。。但是,向正在传递到弹出式构造函数中的内容组件中添加鼠标侦听器
可能会起作用?这是一个很好的解决方案。将WindowFocusListener界面添加到弹出窗口就可以做到这一点。我最终使用了JWindow而不是JDialog,因为我不想要窗口装饰。我将发布最终的解决方案。我也能够让这种方法起作用。结果就简单多了。显然,菜单失去焦点时隐藏的行为只有在将主框架作为show()方法的调用程序传递时才起作用。如果您使用setVisible(true),您将无法获得所需的行为。我也经常这样做。只需将JPOppMenu的布局设置为BorderLayout,并使用中心约束添加内容。JPopupMenu呈现任意swing内容没有问题。我尝试了更多的态度(无边界JDialog、javax.swing.Popup),这似乎是最好的解决方案。