Java Swing,从系统托盘还原,无法在Linux中运行

时间:2014-06-19 20:48:24

标签: java linux swing

我正在用Java创建一个应用程序,我希望当你最小化到一个图标时,应用程序将不得不“隐藏”在系统托盘中。 我使用的代码是:(代码的重要部分)

myFrame = new JFrame();
myFrame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowIconified(WindowEvent e) {                
                PutTray();
            }

            @Override
            public void windowDeiconified(WindowEvent e) {
                System.out.println("Deiconified");

            }

        });

这是“PutTray”功能:

private void PutTray()
    {
            try 
            {
                tray.add(trayIcon); // Initialized elsewhere
                myFrame.setVisible(false);

            } catch (AWTException e) {
                System.err.println(e);
            }
    }

要恢复(按最小化图标时弹出菜单中的选项):

MenuItem show = new MenuItem("Show");
            show.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {


                    myFrame.setVisible(true); 
                    myFrame.setState(JFrame.NORMAL);
                    tray.remove(trayIcon);

                }
            });

该代码在Windows 8上运行良好,但它在Linux(Kali Linux甚至Ubuntu)上不起作用。 为什么Windows是和Linux没有?

修改

在Linux上,按下命令显示应用程序后,它会显示一小段时间,然后再次最小化。基本上是触发事件“windowDeiconified”并在事件“windowIconified”之后立即执行,而不花时间做其他事情,然后应用程序显示在系统托盘中。

1 个答案:

答案 0 :(得分:1)

正如Dan Getz建议的那样,我也认为setVisible和setState的顺序应该被反转,因为setState的javadoc说:

如果在框架上看不到框架      *屏幕,事件可能会也可能不会      *生成。

但这没有帮助。

有一件事虽然有所帮助,但却用dispose()取代了setVisible(false)。它们的相似之处在于您可以使用setVisible(true)重新打开已处理的窗口。您可以在此处详细了解:JDialog setVisible(false) vs dispose() 我会试着找一个解释然后回来:)

SSCCE模拟OP问题:

public class Test {
    private JFrame myFrame;
    public Test() {
        myFrame = new JFrame();
        myFrame.setVisible(true);
        myFrame.setSize(300, 300);
        myFrame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowIconified(WindowEvent e) {
                PutTray();
            }
        });
    }
    private void PutTray() {
        myFrame.setVisible(false); //replace with dispose(); and it's ok
        Timer t = new Timer(1000, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                myFrame.setVisible(true);
            }
        });
        t.setRepeats(false);
        t.start();
    }
    public static void main(String[] args) {
        new Test();
    }
}