JFrame 出于某种原因移到后台
JFrame moves to the background for some reason
在我昨天问了一个关于这个主题的非常模糊的问题后 here(我现在投票决定关闭),我能够查明问题并创建一个显示此行为的 MCVE。
场景是这样的:
虽然一些操作在后台进行,但在前台提供了一个模态“等待”对话框,并且 JFrame 被设置为禁用,以确保万无一失。后台任务完成后,再次启用Frame并释放对话框。
问题是,在启用 JFrame 并处理模式对话框后,JFrame 突然移到后台。具有“背景”的含义,它正在移动到 JFrame 之前具有焦点的 window 后面。为什么会这样?
这段代码应该能重现问题:
private static JFrame frame;
private static JDialog dialog;
public static void main(String[] args) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
buildFrame();
buildDialog();
}
});
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}
protected static void buildDialog() {
dialog = new JDialog(frame);
dialog.getContentPane().add(new JLabel("This is the dialog"));
dialog.setLocationRelativeTo(frame);
javax.swing.Timer t = new javax.swing.Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dialog.dispose();
frame.setEnabled(true);
}
});
t.setRepeats(false);
t.start();
dialog.pack();
dialog.setVisible(true);
}
protected static void buildFrame() {
frame = new JFrame();
frame.setMinimumSize(new Dimension(400, 400));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new JLabel("This is the Frame"));
frame.setEnabled(false);
frame.pack();
frame.setVisible(true);
}
有谁知道为什么会发生这种情况以及如何避免这种情况?
问题出在方法上 frame.setEnabled()
。我不知道为什么,但它隐藏了框架。我的建议是删除它并使用模态概念:dialog.setModal(true)
(它还会在显示对话框时使父框架不可用。要使框架不可用,您可以在其上放置一个玻璃板。代码如下:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseAdapter;
import java.lang.reflect.InvocationTargetException;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
/**
* <code>DialogFrameTest</code>.
*/
public class DialogFrameTest {
private static JFrame frame;
private static JDialog dialog;
private static Component oldGlassPane;
public static void main(String[] args) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
buildFrame();
buildDialog();
}
});
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}
protected static void buildDialog() {
dialog = new JDialog(frame);
dialog.getContentPane().add(new JTextField("This is the dialog"));
dialog.setLocationRelativeTo(frame);
dialog.setModal(true);
javax.swing.Timer t = new javax.swing.Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dialog.dispose();
frame.setGlassPane(oldGlassPane);
oldGlassPane.setVisible(false);
}
});
t.setRepeats(false);
t.start();
dialog.pack();
dialog.setVisible(true);
}
protected static void buildFrame() {
frame = new JFrame();
frame.setMinimumSize(new Dimension(400, 400));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new JTextField("This is the Frame"));
oldGlassPane = frame.getGlassPane();
frame.setGlassPane(new SplashGlassPane());
frame.getGlassPane().setVisible(true);
frame.pack();
frame.setVisible(true);
}
private static class SplashGlassPane extends JPanel implements FocusListener {
/** Holds the id of this panel. The creator of this object can submit this id to determine whether it's the owner of this object. */
private String typeId;
/**
* Creates new GlassPane.
*/
public SplashGlassPane() {
addMouseListener(new MouseAdapter() {});
addMouseMotionListener(new MouseAdapter() {});
addFocusListener(this);
setOpaque(false);
setFocusable(true);
setBackground(new Color(0, 0, 0, 100));
}
@Override
public final void setVisible(boolean v) {
// Make sure we grab the focus so that key events don't go astray.
if (v) {
requestFocus();
}
super.setVisible(v);
}
// Once we have focus, keep it if we're visible
@Override
public final void focusLost(FocusEvent fe) {
if (isVisible()) {
requestFocus();
}
}
/**
* {@inheritDoc}
*/
@Override
public final void paint(Graphics g) {
final Color old = g.getColor();
g.setColor(getBackground());
g.fillRect(0, 0, getSize().width, getSize().height);
g.setColor(old);
super.paint(g);
}
@Override
public void focusGained(FocusEvent fe) {
// nothing to do
}
}
}
在我昨天问了一个关于这个主题的非常模糊的问题后 here(我现在投票决定关闭),我能够查明问题并创建一个显示此行为的 MCVE。
场景是这样的:
虽然一些操作在后台进行,但在前台提供了一个模态“等待”对话框,并且 JFrame 被设置为禁用,以确保万无一失。后台任务完成后,再次启用Frame并释放对话框。
问题是,在启用 JFrame 并处理模式对话框后,JFrame 突然移到后台。具有“背景”的含义,它正在移动到 JFrame 之前具有焦点的 window 后面。为什么会这样?
这段代码应该能重现问题:
private static JFrame frame;
private static JDialog dialog;
public static void main(String[] args) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
buildFrame();
buildDialog();
}
});
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}
protected static void buildDialog() {
dialog = new JDialog(frame);
dialog.getContentPane().add(new JLabel("This is the dialog"));
dialog.setLocationRelativeTo(frame);
javax.swing.Timer t = new javax.swing.Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dialog.dispose();
frame.setEnabled(true);
}
});
t.setRepeats(false);
t.start();
dialog.pack();
dialog.setVisible(true);
}
protected static void buildFrame() {
frame = new JFrame();
frame.setMinimumSize(new Dimension(400, 400));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new JLabel("This is the Frame"));
frame.setEnabled(false);
frame.pack();
frame.setVisible(true);
}
有谁知道为什么会发生这种情况以及如何避免这种情况?
问题出在方法上 frame.setEnabled()
。我不知道为什么,但它隐藏了框架。我的建议是删除它并使用模态概念:dialog.setModal(true)
(它还会在显示对话框时使父框架不可用。要使框架不可用,您可以在其上放置一个玻璃板。代码如下:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseAdapter;
import java.lang.reflect.InvocationTargetException;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
/**
* <code>DialogFrameTest</code>.
*/
public class DialogFrameTest {
private static JFrame frame;
private static JDialog dialog;
private static Component oldGlassPane;
public static void main(String[] args) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
buildFrame();
buildDialog();
}
});
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}
protected static void buildDialog() {
dialog = new JDialog(frame);
dialog.getContentPane().add(new JTextField("This is the dialog"));
dialog.setLocationRelativeTo(frame);
dialog.setModal(true);
javax.swing.Timer t = new javax.swing.Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dialog.dispose();
frame.setGlassPane(oldGlassPane);
oldGlassPane.setVisible(false);
}
});
t.setRepeats(false);
t.start();
dialog.pack();
dialog.setVisible(true);
}
protected static void buildFrame() {
frame = new JFrame();
frame.setMinimumSize(new Dimension(400, 400));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new JTextField("This is the Frame"));
oldGlassPane = frame.getGlassPane();
frame.setGlassPane(new SplashGlassPane());
frame.getGlassPane().setVisible(true);
frame.pack();
frame.setVisible(true);
}
private static class SplashGlassPane extends JPanel implements FocusListener {
/** Holds the id of this panel. The creator of this object can submit this id to determine whether it's the owner of this object. */
private String typeId;
/**
* Creates new GlassPane.
*/
public SplashGlassPane() {
addMouseListener(new MouseAdapter() {});
addMouseMotionListener(new MouseAdapter() {});
addFocusListener(this);
setOpaque(false);
setFocusable(true);
setBackground(new Color(0, 0, 0, 100));
}
@Override
public final void setVisible(boolean v) {
// Make sure we grab the focus so that key events don't go astray.
if (v) {
requestFocus();
}
super.setVisible(v);
}
// Once we have focus, keep it if we're visible
@Override
public final void focusLost(FocusEvent fe) {
if (isVisible()) {
requestFocus();
}
}
/**
* {@inheritDoc}
*/
@Override
public final void paint(Graphics g) {
final Color old = g.getColor();
g.setColor(getBackground());
g.fillRect(0, 0, getSize().width, getSize().height);
g.setColor(old);
super.paint(g);
}
@Override
public void focusGained(FocusEvent fe) {
// nothing to do
}
}
}