2011-12-10 2 views
9

Привет, Я пытаюсь показать более подробную информацию после того, как пользователь нажимает на всплывающую подсказку всплывающего сообщения.Как захватить trayicon.displayMessage() щелчок мышью по подсказке baloon

Однако я не могу найти, как захватить это событие.

Это можно сделать?

+1

good question +1 – mKorbel

ответ

11

1) Есть возможность прослушивания MouseClickEvents от добавления ActionListener к TrayIcon, то тело сообщения для прослушивания MouseClicked

2) (не прямой вопрос), но я не могу дать вам ответ прослушивания, если сообщение было закрыто по кнопке закрытия, и сообщения ушли от экрана точно так же, но без какого-либо поймать событие (ы)

3) выглядит так как это Java TrayIcon message close button должен быть только один решением, потому что API не реализует другие методы,

import java.awt.*; 
import java.awt.event.*; 

public class FullTray { 

    private static class ShowMessageListener implements ActionListener { 

     private TrayIcon trayIcon; 
     private String title; 
     private String message; 
     private TrayIcon.MessageType messageType; 

     ShowMessageListener(TrayIcon trayIcon, String title, String message, TrayIcon.MessageType messageType) { 
      this.trayIcon = trayIcon; 
      this.title = title; 
      this.message = message; 
      this.messageType = messageType; 
     } 

     public void actionPerformed(ActionEvent e) { 
      trayIcon.addActionListener(new ActionListener() { 

       public void actionPerformed(ActionEvent e) { 
        System.out.println("Message Clicked"); 
       } 
      }); 
      trayIcon.displayMessage(title, message, messageType); 
     } 
    } 

    public static void main(String args[]) { 
     Runnable runner = new Runnable() { 

      public void run() { 
       if (SystemTray.isSupported()) { 
        final SystemTray tray = SystemTray.getSystemTray(); 
        Image image = Toolkit.getDefaultToolkit().getImage("gifIcon.gif"); 
        PopupMenu popup = new PopupMenu(); 
        final TrayIcon trayIcon = new TrayIcon(image, "The Tip Text", popup); 
        MenuItem item = new MenuItem("Error"); 
        item.addActionListener(new ShowMessageListener(trayIcon, "Error Title", "Error", TrayIcon.MessageType.ERROR)); 
        popup.add(item); 
        item = new MenuItem("Warning"); 
        item.addActionListener(new ShowMessageListener(trayIcon, "Warning Title", "Warning", TrayIcon.MessageType.WARNING)); 
        popup.add(item); 
        item = new MenuItem("Info"); 
        item.addActionListener(new ShowMessageListener(trayIcon, "Info Title", "Info", TrayIcon.MessageType.INFO)); 
        popup.add(item); 
        item = new MenuItem("None"); 
        item.addActionListener(new ShowMessageListener(trayIcon, "None Title", "None", TrayIcon.MessageType.NONE)); 
        popup.add(item); 
        item = new MenuItem("Close"); 
        item.addActionListener(new ActionListener() { 

         public void actionPerformed(ActionEvent e) { 
          tray.remove(trayIcon); 
         } 
        }); 
        popup.add(item); 
        try { 
         tray.add(trayIcon); 
        } catch (AWTException e) { 
         System.err.println("Can't add to tray"); 
        } 
       } else { 
        System.err.println("Tray unavailable"); 
       } 
      } 
     }; 
     EventQueue.invokeLater(runner); 
    } 

    private FullTray() { 
    } 
} 
+1

+1 Работает на Mac OS X, тоже. – trashgod

+0

Это не работает, если они нажимают «x» на воздушном шаре, я полагаю ... – rogerdpack

+0

Я уведомлен в своей точке 3-го. о ..., может быть, я почтовый код для этого мероприятия на этом форуме тоже, не уверен – mKorbel

2

Несмотря на то, что эта тема не совсем недавно, я решил, что поделюсь своим решением, так как это не изменится.


Как использовать

Чтобы использовать этот код, просто создать 1 открытый класс и 2 открытых интерфейсов.

Теперь создадим экземпляр CustomTrayIcon класса и вызвать метод addToSystemTray(), как только вы закончите его инициализации.

В любое время, когда вы хотите показать оповещение, вызовите showBubbleNotification (...) метод.

Чтобы удалить этот значок в трее, просто вызовите метод removeFromSystemTray().


CustomTrayIcon

Этот класс является базой, которая делает все тяжелую.

package com.samples; 

import java.awt.AWTException; 
import java.awt.Image; 
import java.awt.PopupMenu; 
import java.awt.SystemTray; 
import java.awt.TrayIcon; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 

/** 
* This class can be used to create an icon in the {@link SystemTray}, providing 
* the current operating system supports the {@link SystemTray}. <br /> 
* <br /> 
* <b><u>Userful Methods</u>:</b> 
* <ul> 
* <li> 
* Use the {@link CustomTrayIcon#addToSystemTray() addToSystemTray()} method to 
* add this {@link CustomTrayIcon} to the {@link SystemTray}. <br /> 
* </li> 
* <li> 
* Use the {@link CustomTrayIcon#removeFromSystemTray() removeFromSystemTray()} 
* method to remove this {@link CustomTrayIcon} from the {@link SystemTray}. <br /> 
* </li> 
* <li> 
* Use the 
* {@link CustomTrayIcon#showBubbleNotification(String, String, MessageType, CustomTrayIconNotificationBubbleClickEvent) 
* showBubbleNotification(String, String, MessageType, 
* CustomTrayIconNotificationBubbleClickEvent)} method to show a bubble notification to 
* the user. <br /> 
* </li> 
* <li> 
* Use the {@link CustomTrayIcon#setClickDetectionDelay_override(int) 
* setClickDetectionDelay_override(int)} method to override the default delay to 
* be used when detecting if a user performed a single/double/triple click.</li> 
* </ul> 
* 
* @author Matthew Weiler 
* */ 
public abstract class CustomTrayIcon extends TrayIcon implements CustomTrayIconMouseInterface 
{ 

    /* PRIVATE CONSTANTS */ 
    /** 
    * This will be used as the millisecond delay between clicks to detect 
    * single or double clicks. <br /> 
    * <br /> 
    * <b><u>Default Value</u>:</b> 300 
    * */ 
    private static final int DEFAULT_CLICK_DETECTION_DELAY = 300; 
    /** 
    * This will be used to ensure that we can synchronize the click counter 
    * changes. 
    * */ 
    private static final Object clickLock = new Object(); 

    /* PRIVATE VARIABLES */ 
    /** 
    * This will store the override value to be used in-place of the 
    * {@link CustomTrayIcon#DEFAULT_CLICK_DETECTION_DELAY CLICK_DETECTION_DELAY} 
    * default value. 
    * 
    * @see CustomTrayIcon#DEFAULT_CLICK_DETECTION_DELAY 
    * */ 
    private int clickDetectionDelay_override = -1; 
    /** 
    * This will store the {@link CustomTrayIconNotificationBubbleClickEvent} which 
    * should be executed the next time that an {@link ActionEvent} is fired by 
    * the user clicking a notification bubble. 
    * */ 
    private CustomTrayIconNotificationBubbleClickEvent newBubbleAction = null; 
    /** 
    * This will be used to keep track of which click was responsible for the 
    * current click timer. 
    * */ 
    private long clickOwnerIndex = 0L; 
    /** 
    * This will be used to keep track of how many clicks occurred in the 
    * current click detection cycle. 
    * */ 
    private int clickCounter = 0; 

    /* CONSTRUCTORS */ 
    /** 
    * This will create a new instance of a {@link CustomTrayIcon}. 
    * 
    * @param image 
    *   The {@link Image} to display as the icon in the notification 
    *   tray. 
    * */ 
    public CustomTrayIcon(final Image image) 
    { 
     super(image); 
     this.postCreateTasks(); 
    } 

    /** 
    * This will create a new instance of a {@link CustomTrayIcon}. 
    * 
    * @param image 
    *   The {@link Image} to display as the icon in the notification 
    *   tray. 
    * @param tooltip 
    *   The string to be used as tooltip text; if the value is null no 
    *   tooltip is shown. 
    * */ 
    public CustomTrayIcon(final Image image, final String tooltip) 
    { 
     super(image, tooltip); 
     this.postCreateTasks(); 
    } 

    /** 
    * This will create a new {@link CustomTrayIcon}. <br /> 
    * The {@link CustomTrayIcon} 
    * */ 
    public CustomTrayIcon(final Image image, final String tooltip, final PopupMenu popup) 
    { 
     super(image, tooltip, popup); 
     this.postCreateTasks(); 
    } 

    /* PUBLIC METHODS */ 
    /** 
    * This will determine if the current operating system supports 
    * {@link SystemTray}. 
    * 
    * @see SystemTray#isSupported() 
    * 
    * @return <code>true</code> if the current operating system supports 
    *   {@link SystemTray}; <code>false</code> otherwise. 
    * */ 
    public static boolean isSystemTraySupported() 
    { 
     return SystemTray.isSupported(); 
    } 

    /** 
    * This method will add this {@link CustomTrayIcon} to {@link SystemTray} . <br /> 
    * <br /> 
    * <i>this method may return <code>false</code> if the current operating 
    * system does not have or support a {@link SystemTray}</i> 
    * 
    * @return <code>true</code> if this {@link CustomTrayIcon} was added; 
    *   <code>false</code> otherwise. 
    * */ 
    public boolean addToSystemTray() 
    { 
     // Ensure that the current operating system supports 
     // the SystemTray. 
     if (CustomTrayIcon.isSystemTraySupported()) 
     { 
      try 
      { 
       // Add this CustomTrayIcon to the SystemTray. 
       SystemTray.getSystemTray().add(this); 
       return true; 
      } 
      catch (AWTException e) 
      { 
       // ignore 
      } 
     } 
     return false; 
    } 

    /** 
    * This method will remove this {@link CustomTrayIcon} from the 
    * {@link SystemTray}. 
    * */ 
    public void removeFromSystemTray() 
    { 
     SystemTray.getSystemTray().remove(this); 
    } 

    @Override 
    public void displayMessage(final String caption, final String text, final MessageType messageType) 
    { 
     this.newBubbleAction = null; 
     super.displayMessage(caption, text, messageType); 
    } 

    /** 
    * This method will show a bubble notification near the 
    * {@link CustomTrayIcon}. 
    * 
    * @see TrayIcon#displayMessage(String, String, MessageType) 
    * 
    * @param title 
    *   The title to be displayed in the bubble notification. 
    * @param message 
    *   The message to be displayed in the bubble notification. 
    * @param messageType 
    *   The type of {@link MessageType} which will denote the style of 
    *   the bubble notification. 
    * @param actionOnClick 
    *   The {@link CustomTrayIconNotificationBubbleClickEvent} which should be 
    *   fired when the user clicks the bubble notification. 
    * 
    * @throws NullPointerException 
    *    If both caption and text are <code>null</code>. 
    * */ 
    public void displayMessage(final String title, final String message, final MessageType messageType, final CustomTrayIconNotificationBubbleClickEvent actionOnClick) 
    { 
     this.showBubbleNotification(title, message, messageType, actionOnClick); 
    } 

/** 
* This method will show a bubble notification near the 
* {@link CustomTrayIcon}. 
* 
* @see TrayIcon#displayMessage(String, String, MessageType) 
* 
* @param title 
*   The title to be displayed in the bubble notification. 
* @param message 
*   The message to be displayed in the bubble notification. 
* @param messageType 
*   The type of {@link MessageType} which will denote the style of 
*   the bubble notification. 
* 
* @throws NullPointerException 
*    If both caption and text are <code>null</code>. 
* */ 
public void showBubbleNotification(final String title, final String message, final MessageType messageType) 
{ 
    this.showBubbleNotification(title, message, messageType, null); 
} 

    /** 
    * This method will show a bubble notification near the 
    * {@link CustomTrayIcon}. 
    * 
    * @see TrayIcon#displayMessage(String, String, MessageType) 
    * 
    * @param title 
    *   The title to be displayed in the bubble notification. 
    * @param message 
    *   The message to be displayed in the bubble notification. 
    * @param messageType 
    *   The type of {@link MessageType} which will denote the style of 
    *   the bubble notification. 
    * @param actionOnClick 
    *   The {@link CustomTrayIconNotificationBubbleClickEvent} which should be 
    *   fired when the user clicks the bubble notification. 
    * 
    * @throws NullPointerException 
    *    If both caption and text are <code>null</code>. 
    * */ 
    public void showBubbleNotification(final String title, final String message, final MessageType messageType, final CustomTrayIconNotificationBubbleClickEvent actionOnClick) 
    { 
     this.newBubbleAction = actionOnClick; 
     super.displayMessage(title, message, messageType); 
    } 

    /* GETTERS & SETTERS */ 
    /** 
    * This will get the override value to be used in-place of the 
    * {@link CustomTrayIcon#DEFAULT_CLICK_DETECTION_DELAY CLICK_DETECTION_DELAY} 
    * default value. 
    * 
    * @see CustomTrayIcon#DEFAULT_CLICK_DETECTION_DELAY 
    * 
    * @return The override value to be used in-place of the 
    *   {@link CustomTrayIcon#DEFAULT_CLICK_DETECTION_DELAY 
    *   CLICK_DETECTION_DELAY} default value. 
    * */ 
    public int getClickDetectionDelay_override() 
    { 
     return this.clickDetectionDelay_override; 
    } 

    /** 
    * This will set the override value to be used in-place of the 
    * {@link CustomTrayIcon#DEFAULT_CLICK_DETECTION_DELAY CLICK_DETECTION_DELAY} 
    * default value. 
    * 
    * @see CustomTrayIcon#DEFAULT_CLICK_DETECTION_DELAY 
    * 
    * @param clickDetectionDelay_override 
    *   The override value to be used in-place of the 
    *   {@link CustomTrayIcon#DEFAULT_CLICK_DETECTION_DELAY 
    *   CLICK_DETECTION_DELAY} default value. 
    * */ 
    public void setClickDetectionDelay_override(final int clickDetectionDelay_override) 
    { 
     this.clickDetectionDelay_override = clickDetectionDelay_override; 
    } 

    /* PRIVATE METHODS */ 
    /** 
    * This method will return the delay to have between each click when 
    * determining if the user performed a single/double/triple click. 
    * 
    * @return The delay to have between each click when determining if the user 
    *   performed a single/double/triple click. 
    * */ 
    private int getClickDetectionDelay() 
    { 
     if (this.clickDetectionDelay_override > 0) 
     { 
      return this.clickDetectionDelay_override; 
     } 
     return CustomTrayIcon.DEFAULT_CLICK_DETECTION_DELAY; 
    } 

    /** 
    * This method will be executed as the constructors last task. <br /> 
    * <br /> 
    * <i>this method will set some attributes on this {@link CustomTrayIcon} and 
    * apply the appropriate listeners</i> 
    * */ 
    private void postCreateTasks() 
    { 
     this.setImageAutoSize(true); 
     this.applyCustomListeners(); 
    } 

    /** 
    * This will apply the various listeners to this {@link CustomTrayIcon} 
    * object. 
    * */ 
    private void applyCustomListeners() 
    { 
     // Add an ActionListener which will fire when the user 
     // clicks a bubble notification. 
     this.addActionListener(new ActionListener() 
     { 
      @Override 
      public void actionPerformed(ActionEvent e) 
      { 
       if (CustomTrayIcon.this.newBubbleAction != null) 
       { 
        CustomTrayIcon.this.newBubbleAction.button1_click(); 
        CustomTrayIcon.this.newBubbleAction = null; 
       } 
      } 
     }); 
     // Add a MouseListener on this CustomTrayIcon which will 
     // fire when the user interacts with this CustomTrayIcon 
     // using their mouse. 
     this.addMouseListener(new MouseListener() 
     { 
      @Override 
      public void mouseReleased(MouseEvent arg0) 
      { 
       // NOT SUPPORTED BY TrayIcon 
      } 

      @Override 
      public void mousePressed(MouseEvent arg0) 
      { 
       // NOT SUPPORTED BY TrayIcon 
      } 

      @Override 
      public void mouseExited(MouseEvent arg0) 
      { 

      } 

      @Override 
      public void mouseEntered(MouseEvent arg0) 
      { 

      } 

      @Override 
      public void mouseClicked(MouseEvent arg0) 
      { 
       // Clear the bubble notification action as any open 
       // bubbles should be popped/closed when this interaction 
       // occurs. 
       CustomTrayIcon.this.newBubbleAction = null; 
       // If this MouseEvent was triggered by mouse button 1 
       // being clicked... then continue. 
       if (arg0.getButton() == MouseEvent.BUTTON1) 
       { 
        long tmp_clickOwnerIndex = 0L; 
        // Ensure that only one thread can modify the click owner index 
        // at any given time. 
        synchronized (CustomTrayIcon.clickLock) 
        { 
         // Increase the click owner index so that only the very 
         // last click can fire an event. 
         CustomTrayIcon.this.clickOwnerIndex++; 
         // Store the current value of the click owner index 
         tmp_clickOwnerIndex = CustomTrayIcon.this.clickOwnerIndex; 
        } 
        // Extract the click owner index, which was obtained in a 
        // thread-safe way, into a final variable so we can access it 
        // below. 
        final long tmp_clickOwnerIndex_final = tmp_clickOwnerIndex; 
        // Launch a new Thread which will sleep for a pre-determined 
        // period of time to catch the delay of a double/triple click. 
        (new Thread() 
        { 
         int tmp_clickCounter = 0; 

         public void run() 
         { 
          // Ensure that only one thread can modify the click 
          // counter at any given time. 
          synchronized (CustomTrayIcon.clickLock) 
          { 
           // Increase the number of active clicks that occurred 
           // during the current detection cycle. 
           CustomTrayIcon.this.clickCounter++; 
           // Extract the total number of active clicks that occurred 
           // during the current detection cycle up to this point. 
           tmp_clickCounter = CustomTrayIcon.this.clickCounter; 
          } 
          try 
          { 
           // Sleep for the pre-determined multiple click detection 
           // time. 
           // This ensures that we give the use enough time to 
           // actually perform multiple clicks. 
           Thread.sleep(CustomTrayIcon.this.getClickDetectionDelay()); 
          } 
          catch (InterruptedException e) 
          { 
           // ignore 
          } 
          // Ensure that only one thread can modify the click owner index 
          // at any given time. 
          synchronized (CustomTrayIcon.clickLock) 
          { 
           // If this click was the last click since the appropriate 
           // delay, then it's clear that this click should be 
           // processed. 
           if (CustomTrayIcon.this.clickOwnerIndex == tmp_clickOwnerIndex_final) 
           { 
            // If only one click occurred during the allocated delayed 
            // time, then fire a button 1 click. 
            if (tmp_clickCounter == 1) 
            { 
             CustomTrayIcon.this.button1_click(); 
            } 
            // If two clicks occurred during the allocated delayed 
            // time, then fire a button 2 click. 
            else if (tmp_clickCounter == 2) 
            { 
             CustomTrayIcon.this.button1_doubleClick(); 
            } 
            // If three clicks occurred during the allocated delayed 
            // time, then fire a button 3 click. 
            else if (tmp_clickCounter == 3) 
            { 
             CustomTrayIcon.this.button1_tripleClick(); 
            } 
           } 
           // Decrease the click owner index which will reset the 
           // click stack. 
           CustomTrayIcon.this.clickCounter--; 
          } 
         } 
        }).start(); 
       } 
       // If this MouseEvent was triggered by mouse button 2 
       // being clicked... then continue. 
       else if (arg0.getButton() == MouseEvent.BUTTON2) 
       { 
        // Ensure that only one thread can modify the click owner index 
        // at any given time. 
        synchronized (CustomTrayIcon.clickLock) 
        { 
         // Increase the click owner index so that only the very 
         // last click can fire an event. 
         CustomTrayIcon.this.clickOwnerIndex++; 
        } 
        CustomTrayIcon.this.button2_click(); 
       } 
       // If this MouseEvent was triggered by mouse button 3 
       // being clicked... then continue. 
       else if (arg0.getButton() == MouseEvent.BUTTON3) 
       { 
        // Ensure that only one thread can modify the click owner index 
        // at any given time. 
        synchronized (CustomTrayIcon.clickLock) 
        { 
         // Increase the click owner index so that only the very 
         // last click can fire an event. 
         CustomTrayIcon.this.clickOwnerIndex++; 
        } 
        CustomTrayIcon.this.button3_click(); 
       } 
      } 
     }); 
    } 

} 

CustomTrayIconMouseInterface

Этот интерфейс используется для экстернализовать различные взаимодействия пользователя с помощью мыши.

package com.samples; 

import javax.swing.Popup; 

/** 
* This interface contains several methods which can be fired when a user 
* interacts with the {@link CustomTrayIcon} using their mouse. 
* 
* @author Matthew Weiler 
* */ 
public interface CustomTrayIconMouseInterface 
{ 

    /** 
    * This method will be fired when the user clicks, with mouse button 1, this 
    * {@link CustomTrayIcon}. 
    * */ 
    public void button1_click(); 

    /** 
    * This method will be fired when the user double-clicks, with mouse button 
    * 1, this {@link CustomTrayIcon}. 
    * */ 
    public void button1_doubleClick(); 

    /** 
    * This method will be fired when the user triple-clicks, with mouse button 
    * 1, this {@link CustomTrayIcon}. 
    * */ 
    public void button1_tripleClick(); 

    /** 
    * This method will be fired when the user clicks, with mouse button 2, this 
    * {@link CustomTrayIcon}. 
    * */ 
    public void button2_click(); 

    /** 
    * This method will be fired when the user clicks, with mouse button 3, this 
    * {@link CustomTrayIcon}. <br /> 
    * <br /> 
    * <i>if a {@link Popup} menu is assigned to this {@link CustomTrayIcon}, it 
    * will still popup regardless of any actions taken by this method</i> 
    * */ 
    public void button3_click(); 

} 

CustomTrayIconNotificationBubbleClickEvent

Этот интерфейс используется экстернализовать взаимодействие с пузырем уведомления.

package com.samples; 

/** 
* This interface contains several methods which can be fired when a user 
* interacts with a bubble notification using their mouse. 
* 
* @author Matthew Weiler 
* */ 
public interface CustomTrayIconNotificationBubbleClickEvent 
{ 

    /** 
    * This method will be fired when the user clicks, with mouse button 1, this 
    * bubble notification. 
    * */ 
    public void button1_click(); 

}