由于某些原因,JFrame移至后台 [英] JFrame moves to the background for some reason

查看:75
本文介绍了由于某些原因,JFrame移至后台的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

昨天我问了一个关于这个主题的非常模糊的问题后,

After I asked a very vague question about this topic yesterday here (which I voted to close now), I was able to pinpoint the problem and create a MCVE which shows this behavior.

场景如下:

虽然某些操作在后台进行,但是模态等待"仍在进行中.可以肯定的是,在前台提供了对话框,并且还将JFrame设置为禁用.后台任务完成后,再次启用框架并放置对话框.

While some operation is ongoing in the background, a Modal "Wait" Dialog is provided in the foreground, also the JFrame is being set to be disabled, just to be sure. After the background task is finished, the Frame is enabled again and the dialog disposed.

问题是,在启用JFrame并放置了模式对话框之后,JFrame突然移至后台.具有背景"意思是,它正在焦点位于JFrame之前的窗口后面移动.为什么会这样?

The issue is, that after the JFrame is being enabled and a modal dialog is disposed, the JFrame suddenly moves to the background. With "background" meaning, it is moving behind the window that had focus before the JFrame. Why does this happen?

此代码应复制该问题:

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);
}

有人知道为什么会发生这种情况以及如何防止这种情况发生吗?

Does anyone know why this happens and how this could be prevented?

推荐答案

问题是方法frame.setEnabled().我不知道为什么,但是它隐藏了框架.我的建议是删除它并使用模态概念:dialog.setModal(true)(它还使显示对话框时父框架不可用.要使该框架不可用,可以在其上放置一个玻璃窗格.这是代码:

The problem is the methods frame.setEnabled(). I don't know why, but it hides the frame. My suggestion is to remove it and use the modality concept: dialog.setModal(true) (it also makes the parent frame unavailable when the dialog is shown. To make the frame unavailable, you can place a glasspane over it. Here is the code:

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
        }
    }

}

这篇关于由于某些原因,JFrame移至后台的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆