Я разработчик 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();
}
});
}
}