Java: щелчок правой кнопкой мыши на TrayIcon отключен на Mac OsX

Я пытаюсь разработать приложение для Mac OsX с помощью иконки в системном трее, поэтому после первой попытки с простым кодом для этого я заметил, что пиктограммы на каждом трее приложений (как системных, так и пользовательских) на Mac OSX (10.8) позволяют чтобы активировать относительное всплывающее меню левой и правой кнопкой мыши, но в моем проекте только левая кнопка (MouseEvent.BOTTON1) вызывает раскрывающееся меню. Вот мой код:

public class SystemTrayDemo
{
    private SystemTray tray;
    private TrayIcon tray_icon;

    public SystemTrayDemo()
    {
        if (!SystemTray.isSupported())
        {
            JOptionPane.showMessageDialog(null, "System tray not supported!");
            return;
        }
        else
           tray = SystemTray.getSystemTray();

        final PopupMenu popup = new PopupMenu(); 

        MenuItem exit = new MenuItem("Exit");

        exit.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                if (tray != null)
                {                    
                    tray.remove(tray_icon);
                    System.exit(0);
                }
            }
        });

        popup.add(exit);

        //add tray icon
        tray_icon = new TrayIcon(getIcon("images/wifi.png"), "Open documents...", popup);
        tray_icon.setImageAutoSize(true);

        try
        {            
            tray.add(tray_icon); // adds icon
        }
        catch (AWTException ex) {}
    }


    private Image getIcon(String name)
    {
        URL _url = getClass().getResource(name);
        return new ImageIcon(_url).getImage();
    }

    public static void main(String args[])
    {
        new SystemTrayDemo();
    }
}

но, как я уже сказал, только с помощью левой кнопки мыши. Поэтому во время следующей попытки я попытался имитировать поведение значков на панели задач всех других приложений, используя MouseListener и вызывая событие левой кнопки при событии правой кнопки мыши, используя метод dispatchEvent(), например так:

    public static void fireMouseEvent(Component c)
    {
        MouseEvent me = new MouseEvent(c, // which
                    MouseEvent.MOUSE_CLICKED, // what
                    System.currentTimeMillis(), // when
                    MouseEvent.BUTTON1_MASK, // no modifiers
                    0, 0, // where: at (10, 10}
                    1, // only 1 click 
                    true); // popup trigger

        c.dispatchEvent(me);
    }

событие будет обработано слушателем мыши, но, очевидно, класс TrayIcon не является подклассом компонента, и поэтому источник MouseEvent имеет значение null, и я получаю NPE. Вот мой MouseListener:

    class MouseAdapt extends java.awt.event.MouseAdapter
    {

        public void mouseClicked(java.awt.event.MouseEvent me)
        {
            int button = me.getButton();

            if(button == java.awt.event.MouseEvent.BUTTON3)
            {
                fireMouseEvent(me.getComponent());
            }
        }
    }

    try
    {            
        tray.add(tray_icon); // aggiungi l'icona
        tray_icon.addMouseListener(new MouseAdapt());
    }
    catch (AWTException ex) {}

Извините за мой английский, я надеюсь, что тот, кто когда-либо имел опыт работы с подобными проектами, сможет мне помочь. Я искал несколько часов, но безуспешно. Спасибо за помощь.

1 ответ

Решение

Изменить: теперь есть библиотека, чтобы исправить все это здесь: https://github.com/dorkbox/SystemTray


чтобы активировать относительное всплывающее меню [TrayIcon], щелкните левой и правой кнопкой мыши

Это просто невозможно на Mac + Java в настоящее время. Использование отражения для вызова основных триггеров, похоже, не помогает. Это ошибка.

https://bugs.openjdk.java.net/browse/JDK-8041890

только левая кнопка (MouseEvent.BOTTON1) вызывает раскрывающееся меню. Вот мой код

Даже это не работает в некоторых версиях Java (7u79), исправленных с помощью обновления...

https://bugs.openjdk.java.net/browse/JDK-7158615

Кроссплатформенная поддержка TrayIcon:

Хоть и немного не по теме, хотел бы добавить, некоторые проекты используют JXTrayIcon выполнить некоторые изящные выпадающие меню в Linux/Windows и т. д. Это также вызывает проблемы на Mac, несмотря на ошибку щелчка, от которой он уже страдает сегодня, а также ошибки с Gnome3, требующие совершенно отдельного взлома. Но на Mac любая попытка использовать оформленные меню заставляет меню задерживаться и является очень плохим опытом для конечного пользователя. Решением, на котором я остановился, было использование AWT для Mac, Swing для всего остального. Поддержка Java TrayIcon остро нуждается в переписывании. JavaFX утверждает, что помогает этой инициативе, но он подготовлен для Java 9. В то же время я придерживаюсь OS-зависимых хаков.

Связанные проблемы с лотками для других платформ

Кроме того, некоторые дистрибутивы Linux, такие как Ubuntu, по умолчанию убирают значок в трее на рабочем столе Unity, что вызывает дополнительные головные боли. /questions/13246050/ispolzuya-zagolovki-http/13246065#13246065

Кроме того, прозрачность значка заменяется серым цветом на рабочих столах с поддержкой Gtk/Gnome или Qt/KDE (страдают как OpenJDK, так и Oracle JRE) /questions/45557654/java-trayicon-ispolzuya-izobrazhenie-s-prozrachnyim-fonom/45557672#45557672 http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6453521

Кроме того, рабочие столы с поддержкой Gnome3 могут показывать его не в том углу, или вообще не показывать, но это может быть неактивным (страдают как OpenJDK, так и Oracle JRE) https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=660157 https://bugzilla.redhat.com/show_bug.cgi?id=1014448

В дополнение к этому на экранах с высоким разрешением в Windows есть ошибка, которая неправильно отображает значок: Windows 8 искажает мой TrayIcon

Итак, в итоге, состояние System Tray в Java в порядке, но из-за сочетания факторов в JDK6, JDK7 и JDK8 довольно фрагментированы и глючат.

Другие вопросы по тегам