Как предотвратить эффект предупреждения JFrame на панели задач

exister спросил: 01 сентября 2018 в 07:22 в: java

Я разработчик Java SE, и наша программа работает только на ОС Windows, программе нужно открывать файлы и отображать в пользовательском интерфейсе, мы отображаем содержимое файла в JInternalFrame и всегда setselected(true), когда файл открывается .

Недавно мы обновили нашу программу от JRE1.6.0_41 до JRE1.8.0_144 для основной ошибки и заметили, что в JRE1.8.0_144, когда наша программа (JFrame) не является сфокусирован и вызывается setselected(true) в JInternalFrame в JFrame, JFrame будет мигать на панели задач, что JRE1.6.0_41 не будет. Некоторые из клиентов считают, что это раздражает, потому что им приходится часто открывать файлы.

Итак, проблема в том, что:

(1) Можно ли отключить эту функцию?

p> (2) Если я не могу, есть ли альтернативный способ избежать эффекта мигания, пока я еще могу setSelected() на JInternalFrame?

Если бы я не объяснил это хорошо , вот пример кода для демонстрации эффекта предупреждения, запустите программу и сворачивайте ее в панель задач в другое окно, затем она должна мигать. Я тестировал его в 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();
            }
        });
    }
}

Обновление 01

p> Это коды обновления, в которых @camickr советует добавлять KeyboardFocusManager и WindowListener, только setselected(true) в JInternalFrame, когда JFrame имеет фокус или фокусировку на JFrame, но предупреждение все же происходит, если вы часто переключаете окна, я думаю, это потому, что JFrame потерял фокус прямо перед setselected(true) на JInternalFrame. Может быть, есть способ улучшить код?
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();
            }
        });
    }
}

Обновить 02

Пробовал getGlobalActiveWindow() и windowActivated/windowDeactivated, при частом переключении часто возникает предупреждение. Ниже приведен тестовый код:

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

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


0 ответов