Java 框架始终仅位于我的程序顶部
我试图在一个未装饰的AlwaysOn顶部框架中创建一种工具栏。因此,我希望我的框架位于主框架之上,而不是位于其他程序的框架之上。我尝试了以下代码:Java 框架始终仅位于我的程序顶部,java,swing,always-on-top,Java,Swing,Always On Top,我试图在一个未装饰的AlwaysOn顶部框架中创建一种工具栏。因此,我希望我的框架位于主框架之上,而不是位于其他程序的框架之上。我尝试了以下代码: public class Test { private static JFrame mainFrame; /** * @param args the command line arguments */ public static void main(String[] args) { Swi
public class Test {
private static JFrame mainFrame;
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
mainFrame = new JFrame("test");
mainFrame.setSize(800,600);
mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
mainFrame.setVisible(true);
A a = new A();
}
});
}
public static class A extends JDialog {
public A() {
super(mainFrame);
setAlwaysOnTop(true);
setFocusable(false);
setSize(80,60);
setVisible(true);
}
}
}
但是,尽管使用了JDialog并对拥有者进行了精确的定义,框架仍然位于其他应用程序的顶部(至少在Ubuntu中是这样。也许结果与其他操作系统不同?)
编辑:
好的,我在对话框中尝试了以下代码:
public static class A extends JDialog {
public A(String name) {
super(mainFrame, name);
setAlwaysOnTop(true);
setFocusable(false);
setSize(80, 60);
setVisible(true);
mainFrame.addWindowListener(new WindowAdapter() {
@Override
public void windowActivated(WindowEvent e) {
A.this.setAlwaysOnTop(true);
}
@Override
public void windowDeactivated(WindowEvent e) {
// A.this.setAlwaysOnTop(false);
A.this.toBack();
}
});
}
}
现在的问题是,当主窗口失去焦点时,对话框会将焦点偷回来,我不明白为什么。例如,我运行我的应用程序,尝试切换到Firefox,Firefox出现并覆盖主机,但A对话框获得焦点并停留在屏幕上。现在,如果我再次选择Firefox,对话框将最终正确地消失。你能解释一下为什么这个对话会成为焦点吗
谢谢只有当父窗口激活时,您才应该使窗口始终位于顶部。大概是这样的:
public class Test {
private static JFrame mainFrame;
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
mainFrame = new JFrame("test");
mainFrame.setSize(800,600);
mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
mainFrame.setVisible(true);
final A a = new A();
mainFrame.addWindowListener(new WindowAdapter() {
/**
* {@inheritDoc}
*/
@Override
public void windowDeactivated(WindowEvent e) {
a.setAlwaysOnTop(false);
}
/**
* {@inheritDoc}
*/
@Override
public void windowActivated(WindowEvent e) {
a.setAlwaysOnTop(true);
}
});
}
});
}
public static class A extends JDialog {
public A() {
super(mainFrame);
setAlwaysOnTop(true);
setFocusable(false);
setSize(80,60);
setVisible(true);
}
}
}
好的,我找到了一个解决方案(不知道它是否是解决方案,但它正在工作,所以…)
我发现setFocusableWindowsState(),它非常适合工具栏。顺便说一下,我不知道我以前的setFocusable(false)是否有任何影响
下一个问题是,这段代码的焦点行为非常怪异:如果我从MyApp切换到Firefox,会发生以下情况:
focus : MyApp -> Firefox
execution of MyDialog.toFront()
focus : Firefox -> MyDialog
MyDialog not focusable !
focus : MyDialog -> MyApp !!!
结果:一切都没有改变
所以我终于有了窍门:就在MyDialog.toFront()之后,您将焦点返回给以前的所有者。我发现唯一能做到这一点而不出错的方法是:mainFrame.toBack()
最终代码:
public class Test {
private static JFrame mainFrame;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
mainFrame = new JFrame("test");
mainFrame.setSize(800,600);
mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
mainFrame.setVisible(true);
A a = new A();
}
});
}
public static class A extends JDialog {
public A() {
super(mainFrame);
setAlwaysOnTop(true);
setFocusableWindowState(false);
setSize(80,60);
setVisible(true);
mainFrame.addWindowListener(new WindowAdapter() {
@Override
public void windowActivated(WindowEvent e) {
A.this.setAlwaysOnTop(true);
A.this.toFront();
}
@Override
public void windowDeactivated(WindowEvent e) {
A.this.setAlwaysOnTop(false);
}
});
}
}
}
我认为您需要通过JNI/JNA
class A extends JFrame
,使用某种本机黑客。如果删除setAlwaysOnTop()
,会发生什么?通常情况下,您的帧应该保持在其他帧的顶部。setAlwaysOnTop()
正在为OS@JoopEggen:多个JFrame:这不是一个好的练习游戏机器人:我试过了。如果我点击主框架,我的对话框就会落后,听起来不错。让我们在我的真实节目中尝试一下。我会让你知道的。好的。我试过你的方法。它不适用于setAlwaysOnTop(false),但适用于toBack()。不过,我还有一个小问题。请看我的编辑。谢谢你的帮助@user1967800当帧位于顶部时,它会窃取焦点。因此,必须将alwaysOnTop设置为false。toBack调用setAlwaysOnTop(false)。不管怎样,我试过了,但是错误仍然存在。我认为这是因为对toBack()的调用太晚了。在引发事件之前,焦点可能已从我的应用转移到另一个应用?我在Windows 10中确认了此解决方案。谢谢