gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 15:54:20 24 4
gpt4 key购买 nike

我是一名 Java SE 开发人员,我们的程序只在 windows 操作系统上运行,程序需要打开文件并在 UI 中显示,我们在 JInternalFrame 中显示文件内容,并且总是 setselected(true) 时文件被打开。

最近我们将我们的程序从 JRE1.6.0_41 更新到 JRE1.8.0_144 一个主要错误,并注意到在 JRE1.8.0_144 中当我们的程序(JFrame ) 未获得焦点并在 JFrame 中的 JInternalFrame 上调用 setselected(true) 时,JFrame 将在任务栏中闪烁,而 JRE1.6.0_41 则不会。有些客户认为这很烦人,因为他们必须经常打开文件。

所以问题是:

(1) 我可以关闭该功能吗?

(2) 如果我不能,是否有其他方法可以避免闪烁效果,同时我仍然可以在 JInternalFrame 上 setSelected()

如果我没有解释好,这里是演示警报效果的示例代码,请运行程序并 将其最小化到任务栏 切换到另一个窗口,然后它应该会闪烁。我在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

这是根据@camickr 建议添加KeyboardFocusManagerWindowListener 的更新代码,仅当JFrame 有时在JInternalFrame 上setselected(true)焦点或 JFrame 获得焦点,但如果您频繁切换窗口,警报仍然会发生,我认为这是因为 JFrame 在 setselected(true) on 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();
}
});
}
}

最佳答案

we display the file contents in JInternalFrame and always setselected(true) when the file is opened.

不知道如何停止任务栏上的闪烁,但您可以通过不自动调用 setSelected() 来更改行为。

例如,您可以:

  1. 仅当框架是 Activity 窗口时调用setSelected()。您可以使用 KeyboardFocusManager 检查窗口是否获得焦点。

  2. 向框架添加一个 WindowListener 并处理 windowActivated 事件以在最近打开的内部框架上调用 setSelected() 方法。

编辑:

run the program and minimize it into taskbar,

首先我要澄清的是,如果我将框架最小化到任务栏,则图标闪烁没有问题。

仅当我单击另一个应用程序时该图标才会闪烁,并且登录框架在仍处于打开状态时失去焦点。

the alert still happen if you switch windows frequently,

我将您的代码更改为:

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

而且我注意到,有时即使在另一个窗口中玩游戏,也会显示“Activity ”。所以出于某种原因,KeyboardFocusManager 返回了一个不正确的值(或者我不明白该方法应该如何工作?)

所以也许您可以尝试使用 getGlobalActiveWindow() 方法来查看它是否有任何不同。

如果没有,那么我的下一个建议是忘记 KeyboardFocusManager 并管理一个 boolean 变量,该变量指示您的框架是否处于 Activity 状态。因此,您可以在 windowActivated 中设置变量 true,在 windowDeactivated 中设置 false。然后在创建框架时测试此变量。

另请注意我是如何更改以下代码的:

//  frame = m_InternalFrameWaitSelected;
m_InternalFrameWaitSelected = frame;

关于java - 如何防止任务栏中的JFrame警报效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52494358/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com