Workaround für JPopup im SystemTray

d4rkY89

Mitglied
Hi,
ich habe für meine Zwecke ein Workaround geschrieben, da man für die TrayIcons nur die AWT-Version ohne Icons nutzen kann. Und da das simple Workaround (1. oder 2. Ergebnis in der Google-Suche) mit dem JPopupMenu auch nicht funktioniert (verschwindet nicht bei verlorenem Fokus, bzw. erhält werder focusGained()- noch focusLost()-Events) habe ich das ganze selber per JDialog gelöst.
Funktioniert soweit für meine Zwecke einwand frei. Es lassen sich nach kurzer Google-Suche auch andere Workarounds mit JDialogs finden aber einige haben scheinbar das Problem, dass sich die Programme nur per System.exit(int) schließen lassen, da sie die dialoge nicht disposen.

In meiner Lösung sollte dies kein Problem darstellen, da der JDialog jedesmal, wenn er verschwindet disposed wird.
Sie ist allerdings auch nicht Vollständig, was die Funktionalität betrifft, da ich sie nur soweit ausgebaut habe, wie ich sie momentan für meine Zwecke brauche. Man kann aber bequem ein PopupMenu über Actions oder JMenuItems aufbauen und addSeperator() ist auch vorhanden. Wer mehr Funktionalität braucht kann diese gerne ergänzen :)

Alles in allem denke ich eine nutzbare Vorlage.

Die 2 Klassen
JXTrayIcon und
JXPopupMenu findet ihr im Anhang gezippt.

und hier ein kleines Beispiel, wie man es nutzen kann:

Java:
private boolean initTray() {
	if (!SystemTray.isSupported())
		return false;
	Dimension trayIconSize = SystemTray.getSystemTray().getTrayIconSize();
	Image img = Toolkit.getDefaultToolkit().getImage("einbild.png");
	// das Bild skalieren
	//{...}
	
	if (img == null)
		return false;	

	JXPopupMenu trayPopup = new JXPopupMenu();
	trayPopup.add(new JMenuItem("TestEntry 1"));
	trayPopup.addSeparator();
	trayPopup.add(new JMenuItem("TestEntry 2"));

	trayIcon = new JXTrayIcon(img, "TrayIcon Tooltip", trayPopup);

	try {
		SystemTray.getSystemTray().add(trayIcon);
		return true;
	} catch (AWTException e) {
		return false;
	}
}

Edit:

Gruß d4rkY89 ;)
 

Anhänge

  • SystemTray.zip
    1,6 KB · Aufrufe: 12
Huhu,

das sollte auch wunderbar funktionieren, bentuze es selber, egal ob ich modale dialoge oder oder oder... benutze, es klappt wunderbar, brauchte nur eine setComponent(JComponent c) methode einfügen...

/*
* Copyright 2008 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.

* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.

* This particular file is subject to the "Classpath" exception as provided
* in the LICENSE file that accompanied this code.

* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package org.widgetfx.ui;

import javax.swing.*;
import javax.swing.event.PopupMenuListener;
import javax.swing.event.PopupMenuEvent;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;

/**
* Based on a blog post from Alexander Potochkin at the following url:
* http://weblogs.java.net/blog/alexfromsun/archive/2008/02/jtrayicon_updat.html
*
* @author Alexander Potochkin
* @author Stephen Chin
* @author Keith Combs
*/
public class JXTrayIcon extends TrayIcon {
private JPopupMenu menu;
private static JDialog dialog;
static {
dialog = new JDialog((Frame) null, "TrayDialog");
dialog.setUndecorated(true);
dialog.setAlwaysOnTop(true);
}

private static PopupMenuListener popupListener = new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
}

@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
dialog.setVisible(false);
}

@Override
public void popupMenuCanceled(PopupMenuEvent e) {
dialog.setVisible(false);
}
};

public JXTrayIcon(Image image) {
super(image);
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
showJPopupMenu(e);
}

@Override
public void mouseReleased(MouseEvent e) {
showJPopupMenu(e);
}
});
}

private void showJPopupMenu(MouseEvent e) {
if (e.isPopupTrigger() && menu != null) {
Dimension size = menu.getPreferredSize();
int adjustedY = e.getY() - size.height;
dialog.setLocation(e.getX(), adjustedY < 0 ? e.getY() : adjustedY);
dialog.setVisible(true);
menu.show(dialog.getContentPane(), 0, 0);
// popup works only for focused windows
dialog.toFront();
}
}

public JPopupMenu getJPopupMenu() {
return menu;
}

public void setJPopupMenu(JPopupMenu menu) {
if (this.menu != null) {
this.menu.removePopupMenuListener(popupListener);
}
this.menu = menu;
menu.addPopupMenuListener(popupListener);
}

}
Quelle: http://code.google.com/p/widgetfx/s...ner/src/org/widgetfx/ui/JXTrayIcon.java?r=187

dennoch finde ich deine lösung auch sehr nett.

Grße Maik
 
Zurück