SystemTray: Programm sol im Hintergrund weiter laufen

programmierer123

Aktives Mitglied
Hallo,
bei Klick auf den Schließen oder Minimieren Button, soll mein Programm nicht geschlossen werden sondern weiterhin im Hintergrund laufen.
Es gibt z.B. die Klassen SystemTray und TrayIcon aber ich weiß trotzdem nicht genau, wie ich das programmieren soll.
Die Klasse TrayIcon hat schon fertigen Code aber ich verstehe nicht alles darin.

Wozu ist z.B. der Code für das PopUpMenu da bzw. was macht der Code?
Brauche ich den gesamten Code?
Brauche ich irgendwelche Listener?

SystemTray:
https://docs.oracle.com/javase/7/docs/api/

TrayIcon:
https://docs.oracle.com/javase/7/docs/api/


Über Eure Hilfe bin ich sehr dankbar.
 
Das ist unabhängig von SystemTray s. Sollte man aber generell nicht machen, weil der User in der Annahme ist, das Programm sei geschlossen, wenn er "das Fester" schließt.
 
bei Klick auf den Schließen oder Minimieren Button, soll mein Programm nicht geschlossen werden sondern weiterhin im Hintergrund laufen.
Wie schliesst du dein Programm denn bisher? Das musst du eben so ändern, dass es nicht beendet sondern nur versteckt wird.
Es gibt z.B. die Klassen SystemTray und TrayIcon aber ich weiß trotzdem nicht genau, wie ich das programmieren soll.
Eine einfache Möglichkeit: Dem SystemTray ein TrayIcon hinzufügen, dem TrayIcon einen ActionListener hinzufügen und den ActionListener so programmieren, dass er dein Programm wieder sichtbar macht.
Wozu ist z.B. der Code für das PopUpMenu da bzw. was macht der Code?
Vermutlich erzeugt er ein Popup-Menü.
Brauche ich den gesamten Code?
Nur wenn du ein Popup-Menü haben willst.
 
Ich habe jetzt versucht so einen TrayIcon zu programmieren.
Könnt ihr mir sagen, warum das Icon nicht unten rechts angezeigt wird?

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 javax.swing.JFrame;

public class TerminSoftware extends JFrame {

    private static final long serialVersionUID = 1L;

    public TerminSoftware() {

        setupInteractions();
        pack();
    }
   
    private void setupInteractions() {
        this.addWindowListener(new MyWindowListener());
    }
   
    private class MyWindowListener extends WindowAdapter{
        @Override
        public void windowClosing(WindowEvent e) {
           
            TrayIcon trayIcon = null;
            {
                if (SystemTray.isSupported()) {
                    // get the SystemTray instance
                    SystemTray tray = SystemTray.getSystemTray();
                    // load an image
                    Image image = Toolkit.getDefaultToolkit().getImage("res/appdefault.png");
                    // create a action listener to listen for default action executed on the tray
                    // icon
                    ActionListener listener = new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                            // execute default action of the application
                            // ...
                            TerminSoftware.this.setVisible(false);
                        }
                    };

                } else {
                    // disable tray option in your application or
                    // perform other actions

                }

            }
           
        }
    }

   
}
 
Das Icon wird jetzt unten rechts angezeigt.
Es fehlen noch folgende Dinge.

- Klick auf Icon in Taskleiste => Fenster verschwindet/erscheint
- PopUpMenu: TerminSoftware beenden listener
- PopUpMenu: TerminSoftware anzeigen listener

Für all die Dinge brauche ich Listener. Wie bekomme ich aber heraus, welche Listener ich für die oberen 3 Sachen verwenden soll?

Mein 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 javax.swing.JFrame;

public class TerminSoftware extends JFrame {

    private static final long serialVersionUID = 1L;

    public TerminSoftware() {

        setupInteractions();
        pack();
    }
   
    private void setupInteractions() {
        this.addWindowListener(new MyWindowListener());
       
    }
   
    private class MyWindowListener extends WindowAdapter{
        @Override
        public void windowClosing(WindowEvent e) {
           
             TrayIcon trayIcon = null;
             if (SystemTray.isSupported()) {
                 // get the SystemTray instance
                 SystemTray tray = SystemTray.getSystemTray();
                 // load an image
                 Image image = Toolkit.getDefaultToolkit().getImage("res/appdefault.png");
                 // create a action listener to listen for default action executed on the tray icon
                 ActionListener listener = new ActionListener() {
                     public void actionPerformed(ActionEvent e) {
                         // execute default action of the application
                         // ...
                     }
                 };
                 // create a popup menu
                 PopupMenu popup = new PopupMenu();
                 // create menu item for the default action
                 MenuItem anzeigen = new MenuItem(Konstanten.PROGRAMMNAME + " anzeigen");
                 anzeigen.addActionListener(listener);
                 popup.add(anzeigen);
                 MenuItem beenden = new MenuItem(Konstanten.PROGRAMMNAME + " beenden");
                 beenden.addActionListener(listener);
                 popup.add(beenden);
                 /// ... add other items
                 // construct a TrayIcon
                 trayIcon = new TrayIcon(image, Konstanten.PROGRAMMNAME, popup);
                 // set the TrayIcon properties
                 trayIcon.addActionListener(listener);
                 // ...
                 // add the tray image
                 try {
                     tray.add(trayIcon);
                 } catch (AWTException ex) {
                     System.err.println(ex);
                 }
                 // ...
             } else {
                 // disable tray option in your application or
                 // perform other actions
                
             }
             // ...
             // some time later
             // the application state has changed - update the image
             if (trayIcon != null) {
                
             }
             // ...
           
        }
       
    }

   
}
 
Wie bekomme ich aber heraus, welche Listener ich für die oberen 3 Sachen verwenden soll?
Das kannst du machen wie du willst. Entweder nimmst du den, den du schon hast oder du programmierst für jedes Objekt einen eigenen. Du kannst ja nachsehen, welche addXxxxxListener-Methoden die jeweiligen Objekte anbieten, um herauszufinden, was für Listener untzerstützt werden.
Klick auf Icon in Taskleiste => Fenster verschwindet/erscheint
Wenn das ein einfacher Klick sein soll, geht das nicht mit einem ActionListener. Dafür könntest du einen MouseListener verwenden.
 
Es wurde soweit programmiert aber eine Sache fehlt noch.
Beim Klick auf das Icon soll die Software ein/ausgeblendet werden. Im Moment passiert das nur bei einem Doppelklick.
Ich finde aber einfach nicht heraus, wo der Fehler liegt.
Könnt ihr mir weiterhelfen?

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());
        }
    }
}
 
Kannst du auch erklären, warum es mit einem Actionlistener nicht geht und man dafür einen MouseListener benötigt?

Aber selbst mit dem MouseListener habe ich immer noch dasselbe Problem. Das Fenster wird nicht ein/ausgeblendet.

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;



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 LeftMouseListener extends MouseAdapter{

                @Override
                public void mouseClicked(MouseEvent e) {
                    if(SwingUtilities.isLeftMouseButton(e) && terminSoftware.isVisible()){
                        terminSoftware.setVisible(false);
                    }
                    else if(SwingUtilities.isLeftMouseButton(e) && !terminSoftware.isVisible()){
                        terminSoftware.setVisible(true);
                    }
                }
            }
            trayIcon.addMouseListener(new LeftMouseListener());

/*
            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());
        }
    }
}
 
Kannst du auch erklären, warum es mit einem Actionlistener nicht geht und man dafür einen MouseListener benötigt?
Ein TrayIcon löst bei einem einfachen Klick eben kein ActionEvent aus, also kann man es dafür nicht verwenden. Ich habe es aber nur unter Windows ausprobiert. Unter anderen Betriebssystemen (oder anderen Desktop-Umgebungen) mag das vielleicht anders sein.
Aber selbst mit dem MouseListener habe ich immer noch dasselbe Problem. Das Fenster wird nicht ein/ausgeblendet.
Ich glaube eher nicht, dass das an diesem Codeausschnitt liegt. Wie benutzt du die Klasse denn? Am besten wäre ein lauffähiges Beispiel.
 
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;



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 LeftMouseListener extends MouseAdapter{

                @Override
                public void mouseClicked(MouseEvent e) {
                    if(SwingUtilities.isLeftMouseButton(e) && terminSoftware.isVisible()){
                        terminSoftware.setVisible(false);
                    }
                    else if(SwingUtilities.isLeftMouseButton(e) && !terminSoftware.isVisible()){
                        terminSoftware.setVisible(true);
                    }
                }
            }
            trayIcon.addMouseListener(new LeftMouseListener());

/*
            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());
        }
    }
}

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;



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);
            }
        });
    }
}
 
Hallo.

Also bei mir wird nur das TrayIcon nicht angezeigt bzw. das Bild dazu.
Aber ein Klick auf das Unsichtbare Icon ruft das Menü auf und führt die Aktion dementsprechend durch.
Z. B Beendet die Anwendung.

Grüße
 
Ja, bei mir funktioniert es auch. Rechtsklick ruft das Menü auf, Linksklick blendet die Anwendung wechselweise ein oder aus. Die kontextabhängige Anpassung der MenuItems ist aber noch fehlerhaft.
 
Das wird daran liegen, dass du das Fenster nicht geschlossen sondern minimiert hast (den Fall hatte ich nicht getestet). Über das TrayIcon schaltest du also nur die Sichtbarkeit des minimierten Fensters um. Das müsstest du eigentlich in der Taskleiste sehen können.
 
Wenn ich auf das Icon klicke, dann wird das Fenster minimiert aber das einblenden funktioniert immer noch nicht.

Java:
class LeftMouseListener extends MouseAdapter{

                @Override
                public void mouseClicked(MouseEvent e) {
                    if(SwingUtilities.isLeftMouseButton(e) && terminSoftware.isVisible()){
                        terminSoftware.setExtendedState(Frame.ICONIFIED);


                    }
                    else if(SwingUtilities.isLeftMouseButton(e) && !terminSoftware.isVisible()){
                        terminSoftware.setExtendedState(Frame.NORMAL);
                    }
                }
            }
            trayIcon.addMouseListener(new LeftMouseListener());
 
Also muss ich überprüfen, ob das Fenster minimiert wurde?
Entweder das oder du sorgst beim Minimieren dafür, dass das Fenster unsichtbar wird. Du mußt dir eben überlegen, wie dein Programm sich verhalten soll und dann setVisible()/isVisible() und setExtendedState()/getExtendedState() entsprechend einsetzen.

Wie mache ich das?
Siehe voriger Absatz. Der Status des Frames ist übrigens eine Bitmaske. Da würde ich deshalb darauf achten, nur das gewünschte Bit zu setzen bzw. abzufragen oder den vorigen Status zu speichern und später wieder herzustellen. Z.B. soll das Fenster ja wahrscheinlich wieder maximiert werden, falls es vor dem Schliessen oder Minimieren maximiert war.
 

Neue Themen


Zurück
Oben