TrayIcon programmieren


#1
Hallo,
das ist mein erstes größere Projekt, deswegen bitte ich um etwas Verständnis für meine Fragen.
In meinem Programm will ich eine Tray Funktion einbauen. Könntet ihr mir erklären, was ich falsch gemacht habe bzw. was ich verändern soll?

Über eure Hilfe wäre ich sehr dankbar!


Meine Fragen:
1) Beim Klick auf das Icon soll das Fenster ein/ausgeblendet werden
2) Wenn das Fenster eingeblendet ist und man auf das Icon mit der rechten Maustaste klickt, dann sollen nur die Menüpunkte "Terminsoftware ausblenden" und "Terminsoftware beenden" angezeigt werden und die entsprechende Aktion durchgeführt werden.
3) Wenn das Fenster ausgeblendet ist und man auf das Icon mit der rechten Maustaste klickt, dann sollen nur die Menüpunkte "Terminsoftware einblenden" und "Terminsoftware beenden" angezeigt werden und die entsprechende Aktion durchgeführt werden.


Code:
Java:
import java.awt.AWTException;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JFrame;

public class TerminSoftware extends JFrame {

    private static final long serialVersionUID = 1L;

    public TerminSoftware() {

       
        new TrayIconFeature(this);
        setupInteractions();
        pack();
    }

    private void setupInteractions() {
        this.addWindowListener(new disappearWindowListener());
    }

    private class disappearWindowListener extends WindowAdapter {
        @Override
        public void windowClosing(WindowEvent e) {
            TerminSoftware.this.setVisible(false);
        }
        @Override
        public void windowDeiconified(WindowEvent e) {
            TerminSoftware.this.setVisible(true);
        }
        @Override
        public void windowIconified(WindowEvent e) {
            TerminSoftware.this.setVisible(false);
        }
    }
}

Java:
import java.awt.AWTException;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.SwingUtilities;

public class TrayIconFeature {

    TerminSoftware terminsoftware;

    public TrayIconFeature(TerminSoftware terminSoftware) {
        this.terminsoftware = terminSoftware;

        {
            TrayIcon trayIcon = null;
            if (!SystemTray.isSupported()) {
                // TODO Meldung ausgeben, bevor Programm beendet wird
                System.exit(-1);
            }

            Image imageIcon = Toolkit.getDefaultToolkit().getImage("res/appdefault.png");
            SystemTray tray = SystemTray.getSystemTray();
            PopupMenu popup = new PopupMenu();

            MenuItem anzeigen = new MenuItem(Konstanten.PROGRAMMNAME + " anzeigen");
            MenuItem ausblenden = new MenuItem(Konstanten.PROGRAMMNAME + " ausblenden");
            MenuItem beenden = new MenuItem(Konstanten.PROGRAMMNAME + " beenden");

            popup.add(anzeigen);
            popup.addSeparator();
            popup.add(ausblenden);
            popup.addSeparator();
            popup.add(beenden);

            trayIcon = new TrayIcon(imageIcon, "TerminSoftware", popup);

            try {
                tray.add(trayIcon);
            } catch (AWTException e) {
                e.printStackTrace();
            }
        }
        setupInteractions();
    }

    private void setupInteractions() {
        terminsoftware.addMouseListener(new iconClicked());

    }

    private class iconClicked extends MouseAdapter {

        @Override
        public void mouseClicked(MouseEvent e) {
            if (TrayIconFeature.this.terminsoftware.isVisible() && SwingUtilities.isLeftMouseButton(e)) {
                TrayIconFeature.this.terminsoftware.setVisible(false);
            } else if (!TrayIconFeature.this.terminsoftware.isVisible() && SwingUtilities.isLeftMouseButton(e)) {
                TrayIconFeature.this.terminsoftware.setVisible(true);
            }
        }

    }
}
 

melmager

Erfahrenes Mitglied
#2
Leider haste nicht erwähnt wie das Programm zu zeit reagiert, aber ich gehe mal davon aus das dich stört das alle
Menu einträge vorhanden sind und die sich nicht verändern.

Code:
popup.add(anzeigen);
popup.addSeparator();
popup.add(ausblenden);
also nur zwei Einträge erstellen und dann noch eine tausch Methode einführen

Code:
public void changeMenuItem(boolean bit) {
if (bit) {
popup.remove(anzeigen);
popup.insert(ausblenden,0);
} else {
popup.remove(ausblenden);
popup.insert(anzeigen,0);
}
}
und das rufste dann vom Mouslistener aus auf.
---
untested
 
#3
Danke, für die Antwort.
Das wird aber nicht das Problem lösen, da nur das Icon unten rechts angezeigt wird. Alles andere funktioniert weiterhin nicht.
Man kann nicht mal auf die Menüpunkte klicken, da ich nicht genau weiß, welche Listener man verwenden soll.
Also es müssten immer noch Punkte 1-3 gemacht werden außer das alle Menüeinträge angezeigt werden.
 
#5
Hallo,
es wurde soweit programmiert. Zwei Dinge funktionieren aber nicht richtig.

1) Beim Klick auf das Icon wird das Fenster nicht ein/ausgeblendet
2) Der switch zwischen TerminSoftware anzeigen/ausblenden funktioniert nicht.

Leider weiß ich nicht, was an meinem Code falsch ist.

Java:
import java.awt.AWTException;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.SwingUtilities;

import org.omg.CORBA.PRIVATE_MEMBER;

public class TrayIconFeature {

    TerminSoftware terminsoftware;

    public TrayIconFeature(TerminSoftware terminSoftware) {
        this.terminsoftware = terminSoftware;

        {
            TrayIcon trayIcon = null;
            if (!SystemTray.isSupported()) {
                // TODO Meldung ausgeben, bevor Programm beendet wird
                System.exit(-1);
            }

            Image imageIcon = Toolkit.getDefaultToolkit().getImage("res/appdefault.png");
            SystemTray tray = SystemTray.getSystemTray();
            PopupMenu popup = new PopupMenu();

            MenuItem anzeigen = new MenuItem(Konstanten.PROGRAMMNAME + " anzeigen");
            MenuItem ausblenden = new MenuItem(Konstanten.PROGRAMMNAME + " ausblenden");
            MenuItem beenden = new MenuItem(Konstanten.PROGRAMMNAME + " beenden");
           
            popup.add(anzeigen);
            popup.add(ausblenden);
            popup.addSeparator();
            popup.add(beenden);

            trayIcon = new TrayIcon(imageIcon, "TerminSoftware", popup);

            try {
                tray.add(trayIcon);
            } catch (AWTException e) {
                e.printStackTrace();
            }

           
            class windowListener extends WindowAdapter {

                @Override
                public void windowClosing(WindowEvent e) {
                    popup.remove(ausblenden);
                    popup.insert(anzeigen,0);

                }

                @Override
                public void windowOpened(WindowEvent e) {
                    popup.remove(anzeigen);
                    popup.insert(ausblenden,0);
                }
               
                @Override
                public void windowDeiconified(WindowEvent e) {
                    popup.remove(anzeigen);
                    popup.insert(ausblenden,0);
                }

                @Override
                public void windowIconified(WindowEvent e) {
                    popup.remove(ausblenden);
                    popup.insert(anzeigen,0);
                }

            }
            terminSoftware.addWindowListener(new windowListener());

           
            class iconListener implements ActionListener {

                @Override
                public void actionPerformed(ActionEvent arg0) {
                    if(terminSoftware.isVisible()) {
                        terminSoftware.setVisible(false);
                    }
                    else {
                        terminSoftware.setVisible(true);
                    }
                }
            }
            trayIcon.addActionListener(new iconListener());
           
           
            class anzeigenListener implements ActionListener {

                @Override
                public void actionPerformed(ActionEvent arg0) {
                    terminSoftware.setVisible(true);
                }
            }
            anzeigen.addActionListener(new anzeigenListener());
           
           
            class ausblendenListener implements ActionListener {

                @Override
                public void actionPerformed(ActionEvent arg0) {
                    terminSoftware.setVisible(false);
                }
            }
            ausblenden.addActionListener(new ausblendenListener());
           
           
            class closeProgram implements ActionListener {

                @Override
                public void actionPerformed(ActionEvent arg0) {
                    System.exit(0);
                }
            }
            beenden.addActionListener(new closeProgram());
        }
    }
}
 

melmager

Erfahrenes Mitglied
#6
Code:
trayIcon = new TrayIcon(imageIcon, "TerminSoftware", popup)       
           try {
                tray.add(trayIcon);
           // der listener fehlte
           tray.addActionListener(new iconListener());

            } catch (AWTException e) {
               e.printStackTrace();
           }
Achja Java Regeln beachten:
variablen, Functionen Name Anfang mit Kleinbuchstabe
Classen Name Anfang mit Grossbuchstabe

also IconListener .......
 

melmager

Erfahrenes Mitglied
#10
habe ich nicht gesehen :(
also : next Step - in die Classe Iconlistener und in die Methode ActionPerformed
eine Ausgabe einbauen um zu prüfen ob das aufgerufen wird.
und der Classe IconListener sollte auch eine Referenz von TerminSoftware übergeben werden.
Im Moment gehe ich davon aus das die Classe IconListener die TerminSoftware nicht kennt.
Erstmal die Ausgabe mit System.out.println("klick"); um zu sehen ob das Ereigniss geht.
 
Zuletzt bearbeitet:
#11
Bei einem Doppelklick werden die Ausgaben in der Konsole geschrieben. Bei einem normalen Klick jedoch nicht.

Hier mal der gesamte Code:

Java:
import java.awt.AWTException;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.SwingUtilities;

import org.omg.CORBA.PRIVATE_MEMBER;

public class TrayIconFeature {

    TerminSoftware terminsoftware;

    public TrayIconFeature(TerminSoftware terminSoftware) {
        this.terminsoftware = terminSoftware;

        {
            TrayIcon trayIcon = null;
            if (!SystemTray.isSupported()) {
                // TODO Meldung ausgeben, bevor Programm beendet wird
                System.exit(-1);
            }

            Image imageIcon = Toolkit.getDefaultToolkit().getImage("res/appdefault.png");
            SystemTray tray = SystemTray.getSystemTray();
            PopupMenu popup = new PopupMenu();

            MenuItem anzeigen = new MenuItem(Konstanten.PROGRAMMNAME + " anzeigen");
            MenuItem ausblenden = new MenuItem(Konstanten.PROGRAMMNAME + " ausblenden");
            MenuItem beenden = new MenuItem(Konstanten.PROGRAMMNAME + " beenden");
          
            popup.add(anzeigen);
            popup.add(ausblenden);
            popup.addSeparator();
            popup.add(beenden);

            trayIcon = new TrayIcon(imageIcon, "TerminSoftware", popup);

            try {
                tray.add(trayIcon);
            } catch (AWTException e) {
                e.printStackTrace();
            }

          
            class windowListener extends WindowAdapter {

                @Override
                public void windowClosing(WindowEvent e) {
                    popup.remove(ausblenden);
                    popup.insert(anzeigen,0);

                }

                @Override
                public void windowOpened(WindowEvent e) {
                    popup.remove(anzeigen);
                    popup.insert(ausblenden,0);
                }
              
              
@Override
               public void windowDeiconified(WindowEvent e) {
                   terminSoftware.setVisible(true);
                   popup.remove(anzeigen);
                   popup.insert(ausblenden,0);
               }

               @Override
               public void windowIconified(WindowEvent e) {
                   terminSoftware.setVisible(false);
                   popup.remove(ausblenden);
                   popup.insert(anzeigen,0);
               }

            }
            terminSoftware.addWindowListener(new windowListener());

          
            class IconListener implements ActionListener {
              
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    if(terminSoftware.isVisible()) {
                        terminSoftware.setVisible(false);
                        System.out.println("Software ist nicht eingeblendet");
                    }
                    else {
                        terminSoftware.setVisible(true);
                        System.out.println("Software ist eingeblendet");
                    }
                }
            }
            trayIcon.addActionListener(new IconListener());
          
          
            class anzeigenListener implements ActionListener {

                @Override
                public void actionPerformed(ActionEvent arg0) {
                    terminSoftware.setVisible(true);
                    popup.remove(anzeigen);
                    popup.insert(ausblenden,0);
                }
            }
            anzeigen.addActionListener(new anzeigenListener());
          
          
            class ausblendenListener implements ActionListener {

                @Override
                public void actionPerformed(ActionEvent arg0) {
                    terminSoftware.setVisible(false);
                    popup.remove(ausblenden);
                    popup.insert(anzeigen,0);
                }
            }
            ausblenden.addActionListener(new ausblendenListener());
          
          
            class closeProgram implements ActionListener {

                @Override
                public void actionPerformed(ActionEvent arg0) {
                    System.exit(0);
                }
            }
            beenden.addActionListener(new closeProgram());
        }
    }
  

}


Java:
import java.awt.AWTException;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JFrame;

public class TerminSoftware extends JFrame {

   private static final long serialVersionUID = 1L;

   public TerminSoftware() {
       new TrayIconFeature(this);
       pack();
   }
}


Java:
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.print.DocFlavor.URL;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import org.omg.CORBA.portable.InputStream;

public class TerminSoftwareDemo {

   public static void main(String[] args) {
       SwingUtilities.invokeLater(new Runnable() {
           public void run() {
               JFrame frame = new TerminSoftware();
               try {
                   UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
               } catch (ClassNotFoundException e) {
                   e.printStackTrace();
               } catch (InstantiationException e) {
                   e.printStackTrace();
               } catch (IllegalAccessException e) {
                   e.printStackTrace();
               } catch (UnsupportedLookAndFeelException e) {
                   e.printStackTrace();
               }
               try {
                   // ImageIcon oben links
                   frame.setIconImage(ImageIO.read(new File("res/appdefault.png")));
               }
               catch (IOException exc) {
                   exc.printStackTrace();
               }
               frame.setTitle("Termin Software");
               frame.setLocationRelativeTo(null);
               frame.setVisible(true);
           }
       });
   }
}
 
Zuletzt bearbeitet:
#12
Es fehlen eigentlich nur noch zwei kleine Sachen:

1) Beim Klick auf das Icon soll die Software ein/ausgeblendet werden. Im Moment passiert das nur bei einem Doppelklick.

2) Wenn man auf den Minimieren Button klickt, und dann auf einblenden bzw. ausblenden, dann bleibt die Software weiterhin nicht sichtbar. Es erscheint nur das Icon in der Symbolleiste, aber es erscheint nicht das Fenster.
 

melmager

Erfahrenes Mitglied
#15
statt die Version:
Code:
tray.addActionListener(new iconListener());
die Version - musst mal testen ob dann der "ich muss doppel klicken" effect
dann weg ist - du musst natürlich nicht zwischen links/rechts unterscheiden - aber man kann es :)

Code:
public class SysTray {

    static Image image = Toolkit.getDefaultToolkit().getImage("tray.gif");

    static TrayIcon trayIcon = new TrayIcon(image, "Tester2");

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        if (SystemTray.isSupported()) {
            System.out.println("tray support");
            SystemTray tray = SystemTray.getSystemTray();

            trayIcon.setImageAutoSize(true);
            trayIcon.addMouseListener(new MouseListener() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    System.out.println(e.getButton());
                 
                }

                @Override
                public void mousePressed(MouseEvent e) {
                    System.out.println("press");
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                   System.out.println("release");
                }

                @Override
                public void mouseEntered(MouseEvent e) {
                    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void mouseExited(MouseEvent e) {
                    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }
             
            });
         
         

            try {
                tray.add(trayIcon);
            } catch (AWTException e) {
                System.err.println("TrayIcon could not be added.");
            }
        }
    }
    // TODO code application logic here
}