简体   繁体   English

如何防止任务栏中的JFrame警报效果

[英]How to prevent JFrame alert effect in taskbar

I am a Java SE developer and our program only run on windows OS, the program need to open files and display in UI, we display the file contents in JInternalFrame and always setselected(true) when the file is opened. 我是Java SE开发人员,我们的程序仅在Windows OS上运行,该程序需要打开文件并在UI中显示,我们在JInternalFrame中显示文件内容,并且在打开文件时始终setselected(true)

Recently we updated our program from JRE1.6.0_41 to JRE1.8.0_144 for a major bug, and noticed that in JRE1.8.0_144 when our program(JFrame) is not focused and call setselected(true) on JInternalFrame in the JFrame, the JFrame would blink in taskbar, which JRE1.6.0_41 would not. 最近,我们将程序从JRE1.6.0_41更新到了JRE1.8.0_144 ,这是一个主要错误,并注意到在JRE1.8.0_144中,当我们的程序(JFrame)未聚焦并在JFrame的JInternalFrame上调用setselected(true)时, JFrame会在任务栏中闪烁,而JRE1.6.0_41不会。 Some of the clients think it is annoying because they have to open files frequently. 一些客户认为这很烦人,因为他们不得不经常打开文件。

So the problem is: 所以问题是:

(1) Can I turn the feature off? (1)我可以关闭该功能吗?

(2) If I can't, is there an alternative way to avoid the blink effect while I can still setSelected() on JInternalFrame? (2)如果我做不到,是否还有其他方法可以避免闪烁效果,而我仍然可以在JInternalFrame上进行setSelected()

If I didn't explain it well, here is the sample code to demo the alert effect, please run the program and minimize it into taskbar switch to another window, then it should blink. 如果我没有很好地解释它,这是演示警报效果的示例代码,请运行该程序并将其 最小化到任务栏 ,然后切换到另一个窗口,然后它应该闪烁。 I have tested it on Windows 7, Windows 8.1 and Windows 10 and they all have the same alert effect. 我已经在Windows 7,Windows 8.1和Windows 10上进行了测试,它们都具有相同的警报效果。

import javax.swing.JInternalFrame;
import javax.swing.SwingUtilities;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;

import java.awt.*;

/*
 * Copy and modified by Oracle sample code "InternalFrameDemo.java"
 */
public class Login extends JFrame {
    JDesktopPane desktop;
    private int m_iFrameCounter = 0;

    public Login() {
        super("InternalFrameDemo");

        //Make the big window be indented 50 pixels from each edge
        //of the screen.
        int inset = 50;
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        setBounds(inset, inset,
                  screenSize.width  - inset*2,
                  screenSize.height - inset*2);

        //Set up the GUI.
        desktop = new JDesktopPane(); //a specialized layered pane
        createFrame(); //create first "window"
        setContentPane(desktop);

        //Make dragging a little faster but perhaps uglier.
        desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);

        // Add new frame every second
        Thread addFrameThread = new Thread() {

            @Override
            public void run() {
                while(true) {
                    SwingUtilities.invokeLater(new Runnable() {

                        @Override
                        public void run() {
                            createFrame();
                        }
                    });
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        addFrameThread.start();
    }

    //Create a new internal frame.
    protected void createFrame() {
        JInternalFrame frame = new JInternalFrame();
        frame.setTitle("" + m_iFrameCounter);
        frame.setSize(100, 100);
        frame.setLocation(0, 0);
        frame.setVisible(true); //necessary as of 1.3
        desktop.add(frame);
        frame.moveToFront();
        try {
            frame.setSelected(true);
        } catch (java.beans.PropertyVetoException e) {}
        m_iFrameCounter++;
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Make sure we have nice window decorations.
        JFrame.setDefaultLookAndFeelDecorated(true);

        //Create and set up the window.
        Login frame = new Login();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Display the window.
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

Update 01 更新01

This is the update codes which take @camickr advice to add KeyboardFocusManager and WindowListener , only setselected(true) on JInternalFrame when JFrame has focus or JFrame gain focus, but the alert still happen if you switch windows frequently, I think it is because JFrame lost focus right before setselected(true) on JInternalFrame. 这是采用@camickr建议的更新代码,以添加KeyboardFocusManagerWindowListener ,仅当JFrame具有焦点或JFrame获得焦点时才在JInternalFrame上setselected(true) ,但是如果您频繁切换窗口,警报仍然会发生,我认为这是因为JFrame丢失了将焦点集中在JInternalFrame上的setselected(true)之前。 Maybe there is a way to improve the code? 也许有一种方法可以改善代码?

import javax.swing.JInternalFrame;
import javax.swing.SwingUtilities;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;

import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.beans.PropertyVetoException;

/*
 * Copy and modified by Oracle sample code "InternalFrameDemo.java"
 */
public class Login extends JFrame {
    JDesktopPane desktop;
    private int m_iFrameCounter = 0;
    private JInternalFrame m_InternalFrameWaitSelected = null;

    public Login() {
        super("InternalFrameDemo");

        //Make the big window be indented 50 pixels from each edge
        //of the screen.
        int inset = 50;
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        setBounds(inset, inset,
                  screenSize.width  - inset*2,
                  screenSize.height - inset*2);

        //Set up the GUI.
        desktop = new JDesktopPane(); //a specialized layered pane
        createFrame(); //create first "window"
        setContentPane(desktop);

        //Make dragging a little faster but perhaps uglier.
        desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);

        /*********************************************  update codes *********************************************/ 
        //Add window listener to set last JInternalframe selected when JFrame activated
        this.addWindowListener(new WindowListener() {

            @Override
            public void windowOpened(WindowEvent e) {
            }

            @Override
            public void windowClosing(WindowEvent e) {
            }

            @Override
            public void windowClosed(WindowEvent e) {
            }

            @Override
            public void windowIconified(WindowEvent e) {
            }

            @Override
            public void windowDeiconified(WindowEvent e) {
            }

            @Override
            public void windowActivated(WindowEvent e) {
                if (m_InternalFrameWaitSelected != null) {
                    try {
                        m_InternalFrameWaitSelected.setSelected(true);
                    } catch (PropertyVetoException e1) {
                        e1.printStackTrace();
                    }
                    m_InternalFrameWaitSelected = null;
                }
            }

            @Override
            public void windowDeactivated(WindowEvent e) {
            }

        });
        /*********************************************  update codes *********************************************/

        // Add new frame every 50 millisecond
        Thread addFrameThread = new Thread() {

            @Override
            public void run() {
                while(true) {
                    SwingUtilities.invokeLater(new Runnable() {

                        @Override
                        public void run() {
                            createFrame();
                        }
                    });
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        addFrameThread.start();
    }

    //Create a new internal frame.
    protected void createFrame() {
        JInternalFrame frame = new JInternalFrame();
        frame.setTitle("" + m_iFrameCounter);
        frame.setSize(100, 100);
        frame.setLocation(0, 0);
        frame.setVisible(true); //necessary as of 1.3
        desktop.add(frame);
        frame.moveToFront();
        /*********************************************  update codes *********************************************/
        // Only setselect(true) when JFrame is focus owner
        if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != null &&
                SwingUtilities.isDescendingFrom(KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(), this)) {
            try {
                frame.setSelected(true);
            } catch (java.beans.PropertyVetoException e) {}
        } else {
            m_InternalFrameWaitSelected = frame;
        }
        /*********************************************  update codes *********************************************/
        m_iFrameCounter++;
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Make sure we have nice window decorations.
        JFrame.setDefaultLookAndFeelDecorated(true);

        //Create and set up the window.
        Login frame = new Login();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Display the window.
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

Update 02 更新02

Tried with getGlobalActiveWindow() and windowActivated/windowDeactivated , alert still happen if switch windows frequently. 使用getGlobalActiveWindow()windowActivated/windowDeactivated尝试过,如果频繁切换窗口,仍然会发生警报。 Below are the test code: 下面是测试代码:

getGlobalActiveWindow() getGlobalActiveWindow()

import javax.swing.JInternalFrame;
import javax.swing.SwingUtilities;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;

import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.beans.PropertyVetoException;

/*
 * Copy and modified by Oracle sample code "InternalFrameDemo.java"
 */
public class Login extends JFrame {
    JDesktopPane desktop;
    private int m_iFrameCounter = 0;
    private JInternalFrame m_InternalFrameWaitSelected = null;
    /*********************************************  update codes *********************************************/ 
    private MyDefaultKeyboardFocusManager m_MyKeyboardFocusManager = new MyDefaultKeyboardFocusManager();

    public class MyDefaultKeyboardFocusManager extends DefaultKeyboardFocusManager {

        //The method is protected, need to add public method to call it
        public Window myGetGlobalActiveWindow() {
            return this.getGlobalActiveWindow();
        }

    }
    /*********************************************  update codes *********************************************/ 

    public Login() {
        super("InternalFrameDemo");

        //Make the big window be indented 50 pixels from each edge
        //of the screen.
        int inset = 50;
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        setBounds(inset, inset,
                  screenSize.width  - inset*2,
                  screenSize.height - inset*2);

        //Set up the GUI.
        desktop = new JDesktopPane(); //a specialized layered pane
        setContentPane(desktop);

        //Make dragging a little faster but perhaps uglier.
        desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);

        /*********************************************  update codes *********************************************/ 
        KeyboardFocusManager.setCurrentKeyboardFocusManager(m_MyKeyboardFocusManager);
        /*********************************************  update codes *********************************************/

        //Add window listener to set last JInternalframe selected when JFrame activated
        this.addWindowListener(new WindowListener() {

            @Override
            public void windowOpened(WindowEvent e) {
            }

            @Override
            public void windowClosing(WindowEvent e) {
            }

            @Override
            public void windowClosed(WindowEvent e) {
            }

            @Override
            public void windowIconified(WindowEvent e) {
            }

            @Override
            public void windowDeiconified(WindowEvent e) {
            }

            @Override
            public void windowActivated(WindowEvent e) {
                if (m_InternalFrameWaitSelected != null) {
                    try {
                        m_InternalFrameWaitSelected.setSelected(true);
                    } catch (PropertyVetoException e1) {
                        e1.printStackTrace();
                    }
                    m_InternalFrameWaitSelected = null;
                }
            }

            @Override
            public void windowDeactivated(WindowEvent e) {
            }

        });

        // Add new frame every 50 millisecond
        Thread addFrameThread = new Thread() {

            @Override
            public void run() {
                while(true) {
                    SwingUtilities.invokeLater(new Runnable() {

                        @Override
                        public void run() {
                            createFrame();
                        }
                    });
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        addFrameThread.start();
    }

    //Create a new internal frame.
    protected void createFrame() {
        JInternalFrame frame = new JInternalFrame();
        frame.setTitle("" + m_iFrameCounter);
        frame.setSize(100, 100);
        frame.setLocation(0, 0);
        frame.setVisible(true); //necessary as of 1.3
        desktop.add(frame);
        frame.moveToFront();
        /*********************************************  update codes *********************************************/
        // Only setselect(true) when JFrame is active
        if (m_MyKeyboardFocusManager.myGetGlobalActiveWindow() == this) {
            try {
                frame.setSelected(true);
            } catch (java.beans.PropertyVetoException e) {}
        } else {
            m_InternalFrameWaitSelected = frame;
        }
        /*********************************************  update codes *********************************************/
        m_iFrameCounter++;
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Make sure we have nice window decorations.
        JFrame.setDefaultLookAndFeelDecorated(true);

        //Create and set up the window.
        Login frame = new Login();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Display the window.
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

windowActivated/windowDeactivated 的windowActivated /的windowDeactivated

import javax.swing.JInternalFrame;
import javax.swing.SwingUtilities;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;

import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.beans.PropertyVetoException;

/*
 * Copy and modified by Oracle sample code "InternalFrameDemo.java"
 */
public class Login extends JFrame {
    JDesktopPane desktop;
    private int m_iFrameCounter = 0;
    private JInternalFrame m_InternalFrameWaitSelected = null;
    /*********************************************  update codes *********************************************/ 
    private boolean m_bIsFrameActive = false;
    /*********************************************  update codes *********************************************/ 

    public Login() {
        super("InternalFrameDemo");

        //Make the big window be indented 50 pixels from each edge
        //of the screen.
        int inset = 50;
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        setBounds(inset, inset,
                  screenSize.width  - inset*2,
                  screenSize.height - inset*2);

        //Set up the GUI.
        desktop = new JDesktopPane(); //a specialized layered pane
        setContentPane(desktop);

        //Make dragging a little faster but perhaps uglier.
        desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);

        /*********************************************  update codes *********************************************/ 
        //Add window listener to set last JInternalframe selected when JFrame activated
        this.addWindowListener(new WindowListener() {

            @Override
            public void windowOpened(WindowEvent e) {
            }

            @Override
            public void windowClosing(WindowEvent e) {
            }

            @Override
            public void windowClosed(WindowEvent e) {
            }

            @Override
            public void windowIconified(WindowEvent e) {
            }

            @Override
            public void windowDeiconified(WindowEvent e) {
            }

            @Override
            public void windowActivated(WindowEvent e) {
                m_bIsFrameActive = true;
                if (m_InternalFrameWaitSelected != null) {
                    try {
                        m_InternalFrameWaitSelected.setSelected(true);
                    } catch (PropertyVetoException e1) {
                        e1.printStackTrace();
                    }
                    m_InternalFrameWaitSelected = null;
                }
            }

            @Override
            public void windowDeactivated(WindowEvent e) {
                m_bIsFrameActive = false;
            }

        });
        /*********************************************  update codes *********************************************/

        // Add new frame every 50 millisecond
        Thread addFrameThread = new Thread() {

            @Override
            public void run() {
                while(true) {
                    SwingUtilities.invokeLater(new Runnable() {

                        @Override
                        public void run() {
                            createFrame();
                        }
                    });
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        addFrameThread.start();
    }

    //Create a new internal frame.
    protected void createFrame() {
        JInternalFrame frame = new JInternalFrame();
        frame.setTitle("" + m_iFrameCounter);
        frame.setSize(100, 100);
        frame.setLocation(0, 0);
        frame.setVisible(true); //necessary as of 1.3
        desktop.add(frame);
        frame.moveToFront();
        /*********************************************  update codes *********************************************/
        // Only setselect(true) when JFrame is active
        if (m_bIsFrameActive) {
            try {
                frame.setSelected(true);
            } catch (java.beans.PropertyVetoException e) {}
        } else {
            m_InternalFrameWaitSelected = frame;
        }
        /*********************************************  update codes *********************************************/
        m_iFrameCounter++;
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Make sure we have nice window decorations.
        JFrame.setDefaultLookAndFeelDecorated(true);

        //Create and set up the window.
        Login frame = new Login();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Display the window.
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

we display the file contents in JInternalFrame and always setselected(true) when the file is opened. 我们在JInternalFrame中显示文件内容,并在打开文件时始终setselected(true)。

Don't know how to stop the blinking on the taskbar, but you can change the behaviour by not automatically invoking setSelected(). 不知道如何停止任务栏上的闪烁,但是您可以通过不自动调用setSelected()来更改行为。

You could for example: 您可以例如:

  1. only invoke setSelected() when the frame is the active window. 仅在框架为活动窗口时才调用setSelected() You can use the KeyboardFocusManager to check if the window is focused. 您可以使用KeyboardFocusManager来检查窗口是否聚焦。

  2. add a WindowListener to the frame and handle the windowActivated event to invoke the setSelected() method on the most recently opened internal frame. WindowListener添加到框架并处理windowActivated事件,以在最近打开的内部框架上调用setSelected()方法。

Edit: 编辑:

run the program and minimize it into taskbar, 运行程序并将其最小化到任务栏中,

First I want to clarify that if I minimize the frame to the taskbar there is no problem with the icon blinking. 首先,我想澄清一下,如果将框架最小化到任务栏,则图标闪烁没有问题。

The icon only blinks if I click on another application and the Login frame loses focus while it is still open. 仅当我单击另一个应用程序时,该图标才会闪烁,并且登录框仍处于打开状态时会失去焦点。

the alert still happen if you switch windows frequently, 如果您经常切换窗口,警报仍然会发生,

I changed your code to: 我将您的代码更改为:

//if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != null &&
//    SwingUtilities.isDescendingFrom(KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(), this)) {
if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow() == this)
{
    try
    {
        System.out.println("active");
        frame.setSelected(true);
    }
    catch (java.beans.PropertyVetoException e) {}
}
else
{
    System.out.println("not");
//  frame = m_InternalFrameWaitSelected;
    m_InternalFrameWaitSelected = frame;
}

and I noticed that sometimes "active" was being displayed at even though is was playing a game in another window. 而且我注意到即使在另一个窗口中玩游戏时,有时也会显示“活动”。 So for some reason the KeyboardFocusManager was returning an incorrect value (or I don't understand how the method should work?) 所以由于某种原因,KeyboardFocusManager返回的值不正确(或者我不知道该方法应如何工作?)

So maybe you can try using the getGlobalActiveWindow() method to see if it makes any difference. 因此,也许您可​​以尝试使用getGlobalActiveWindow()方法来查看它是否有所不同。

If not, then my next suggestion is to forget about the KeyboardFocusManager and manage a Boolean variable that indicates if your frame is active or not. 如果不是,那么我的下一个建议是忘记KeyboardFocusManager并管理一个布尔变量,该变量指示您的框架是否处于活动状态。 So you would set the variable true in windowActivated and false in windowDeactivated. 因此,您将在windowActivated中将变量设置为true,在windowDeactivated中将变量设置为false。 Then you test this variable when you create the frame. 然后在创建框架时测试此变量。

Also note how I changed the following code: 还要注意我如何更改以下代码:

//  frame = m_InternalFrameWaitSelected;
    m_InternalFrameWaitSelected = frame;

If someone is interested about the answer, after I trace down to the source code in JInternalFrame, I find out the blink effect is caused by requestFocus() when setSelected(true) is called, so I decided to inherit JInternalFrame and replace requestFocus() with requestFocusInWindow() , now the blink effect is gone. 如果有人对答案感兴趣,那么我会追溯到JInternalFrame中的源代码后,发现眨眼效果是由setSelected(true)时的requestFocus()引起的,所以我决定继承JInternalFrame并替换requestFocus()使用requestFocusInWindow() ,现在闪烁效果消失了。

Here is my final solution for the issue: 这是我对此问题的最终解决方案:

import javax.swing.JInternalFrame;
import javax.swing.SwingUtilities;

import sun.swing.SwingUtilities2;

import javax.swing.InternalFrameFocusTraversalPolicy;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;

import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.beans.PropertyVetoException;

/*
 * Copy and modified by Oracle sample code "InternalFrameDemo.java"
 */
public class Login extends JFrame {
    JDesktopPane desktop;
    private int m_iFrameCounter = 0;

    /**
     * This class is created to handle problem that program would blink in taskbar 
     * when call setSelected(true) on JInternalFrame base on JRE1.8.0_144, the only different content is
     * use lastFocusOwner.requestFocusInWindow(); instead of lastFocusOwner.requestFocus(); 
     * in method restoreSubcomponentFocus() 
     *
     */
    public class MyInternalFrame extends JInternalFrame {

        private Component lastFocusOwner;
        private final String BASE_JRE_VERSION = "1.8.0_144";

        public MyInternalFrame() {
            _checkJavaVersion();
        }

        public MyInternalFrame(String title) {
            super(title);
            _checkJavaVersion();
        }

        public MyInternalFrame(String title, boolean resizable) {
            super(title, resizable);
            _checkJavaVersion();
        }

        public MyInternalFrame(String title, boolean resizable, boolean closable) {
            super(title, resizable, closable);
            _checkJavaVersion();
        }

        public MyInternalFrame(String title, boolean resizable, boolean closable, boolean maximizable) {
            super(title, resizable, closable, maximizable);
            _checkJavaVersion();
        }

        public MyInternalFrame(String title, boolean resizable, boolean closable, boolean maximizable, boolean iconifiable) {
            super(title, resizable, closable, maximizable, iconifiable);
            _checkJavaVersion();
        }

        private void _checkJavaVersion() {
            if (!BASE_JRE_VERSION.equals(System.getProperty("java.version")))
                System.err.println(String.format("%s is not compatible with current Java runtime version : %s ", this.getClass().toString(), System.getProperty("java.version")));
        }

        @Override
        public void restoreSubcomponentFocus() {
            if (isIcon()) {
                SwingUtilities2.compositeRequestFocus(getDesktopIcon());
            }
            else {
                Component component = KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner();
                if ((component == null) || !SwingUtilities.isDescendingFrom(component, this)) {
                    // FocusPropertyChangeListener will eventually update
                    // lastFocusOwner. As focus requests are asynchronous
                    // lastFocusOwner may be accessed before it has been correctly
                    // updated. To avoid any problems, lastFocusOwner is immediately
                    // set, assuming the request will succeed.
                    setLastFocusOwner(getMostRecentFocusOwner());
                    if (lastFocusOwner == null) {
                        // Make sure focus is restored somewhere, so that
                        // we don't leave a focused component in another frame while
                        // this frame is selected.
                        setLastFocusOwner(getContentPane());
                    }
                    lastFocusOwner.requestFocusInWindow();
                }
            }
        }

        private void setLastFocusOwner(Component component) {
            lastFocusOwner = component;
        }

        @Override
        public Component getMostRecentFocusOwner() {
            if (isSelected()) {
                return getFocusOwner();
            }

            if (lastFocusOwner != null) {
                return lastFocusOwner;
            }

            FocusTraversalPolicy policy = getFocusTraversalPolicy();
            if (policy instanceof InternalFrameFocusTraversalPolicy) {
                return ((InternalFrameFocusTraversalPolicy)policy).
                    getInitialComponent(this);
            }

            Component toFocus = policy.getDefaultComponent(this);
            if (toFocus != null) {
                return toFocus;
            }
            return getContentPane();
        }

        @Override
        public Component getFocusOwner() {
            if (isSelected()) {
                return lastFocusOwner;
            }
            return null;
        }
    }

    public Login() {
        super("InternalFrameDemo");

        //Make the big window be indented 50 pixels from each edge
        //of the screen.
        int inset = 50;
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        setBounds(inset, inset,
                  screenSize.width  - inset*2,
                  screenSize.height - inset*2);

        //Set up the GUI.
        desktop = new JDesktopPane(); //a specialized layered pane
        setContentPane(desktop);

        //Make dragging a little faster but perhaps uglier.
        desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);

        // Add new frame every 50 millisecond
        Thread addFrameThread = new Thread() {

            @Override
            public void run() {
                while(true) {
                    SwingUtilities.invokeLater(new Runnable() {

                        @Override
                        public void run() {
                            createFrame();
                        }
                    });
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        addFrameThread.start();
    }

    //Create a new internal frame.
    protected void createFrame() {
        JInternalFrame frame = new MyInternalFrame();
        frame.setTitle("" + m_iFrameCounter);
        frame.setSize(100, 100);
        frame.setLocation(0, 0);
        frame.setVisible(true); //necessary as of 1.3
        desktop.add(frame);
        frame.moveToFront();
        try {
            frame.setSelected(true);
        } catch (java.beans.PropertyVetoException e) {}
        m_iFrameCounter++;
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Make sure we have nice window decorations.
        JFrame.setDefaultLookAndFeelDecorated(true);

        //Create and set up the window.
        Login frame = new Login();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Display the window.
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM