【问题标题】:JFrame moves to the background for some reasonJFrame 出于某种原因移至后台
【发布时间】:2020-08-21 07:12:42
【问题描述】:

在我昨天就这个话题提出了一个非常模糊的问题here(我现在投票结束)之后,我能够查明问题并创建一个显示这种行为的 MCVE。

场景如下:

当一些操作在后台进行时,前台提供了一个模态“等待”对话框,JFrame 也被设置为禁用,只是为了确定。后台任务完成后,再次启用Frame并释放对话框。

问题是,在启用 JFrame 并释放模态对话框后,JFrame 突然移动到后台。具有“背景”的含义,它在 JFrame 之前具有焦点的窗口后面移动。为什么会这样?

此代码应复制问题:

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.toFront();在 frame.setEnabled(true) 之后;您正在禁用整个框架,请尝试禁用 contentPane 或使用模态对话框。
  • 我尝试使用frame.toFront()。但这只会导致框架迅速消失并再次出现。
  • 为什么要禁用框架?当您显示模态对话框时,用户将无法访问框架,直到对话框关闭。
  • @camickr 我知道,模态对话框会单独处理这个问题,并且完全没有必要禁用框架。但我把这个作为一个要求,例如之后要做的第一件事。按下按钮 xy 是为了禁用整个 UI(即使接下来要显示的是模式对话框)以防止任何类型的“双击”或任何不需要的行为。我只是试图遵守这一点,并遇到了这一点。

标签: java swing jframe jdialog


【解决方案1】:

问题在于方法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
        }
    }

}

【讨论】:

  • 感谢您的意见。我实际上在我的真实代码中使用了模态概念。 IE。 dialog.setModalityType(DEFAULT_MODALITY_TYPE);。但是,尽管有对话的形式,“完全禁用框架”是一项要求。我很好奇为什么组合时会出现这种行为。
  • 我已经更正了我的示例。您应该使用玻璃窗格而不是 frame.setEnabled()
  • 谢谢!这是非常有用的。即使我仍然不知道在这种情况下究竟是什么导致 Frame 被隐藏。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-03
  • 1970-01-01
  • 1970-01-01
  • 2021-08-11
  • 1970-01-01
相关资源
最近更新 更多