Anwendung aus SystemTray öffnen

Diskutiere Anwendung aus SystemTray öffnen im AWT, Swing, JavaFX & SWT Bereich.
OSchriever

OSchriever

Hi Freunde, ich habe ein Programm, welches ich im Hintergrund laufen lasse und als SystemTray-Symbol anzeigen lasse. Ich habe die Anwendung mit dem Scene Builder erstellt und kann über das Symbol die Anwendung schließen. Da sich hier AWT und JavaFX vermischt, ist das für mich als Anfänger etwas schwierig, aber ich habe es soweit fast am laufen, bis auf eine Sache:
Ich möchte die Anwendung per Doppelklick auf das System Tray Icon wieder öffnen. Dafür habe ich den ListenerTray programmiert. Ich weiß aber nicht mit welcher Anweisung ich das hinbekommen soll. Hat jemand eine Idee?

Vielen Dank

Hier der FXML Controller:


Java:
package de.schrieverkommt;


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.TrayIcon.MessageType;
import java.awt.event.ActionListener;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Timer;
import java.util.TimerTask;
import com.sun.nio.sctp.Notification;

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;




public class FXMLController {
    
    @FXML private CheckBox aktivBox;
    @FXML private Label letzteAkt;
    @FXML private Button ausfuehren;
    @FXML private Button anleitung;
    @FXML private Button info;
    @FXML private Button hintergrund;
    @FXML private Pane pane;
    
    TrayIcon trayIcon;
    
    @FXML protected void hintergrundKlick(ActionEvent event) {
        
        Stage stage =(Stage)pane.getScene().getWindow();
        stage.hide();
        
        
        if (SystemTray.isSupported()) {         
            SystemTray tray = SystemTray.getSystemTray();
            Image image = Toolkit.getDefaultToolkit().getImage("C:\\Users\\oschr\\Desktop\\aa.png");
            PopupMenu popup = new PopupMenu();
            MenuItem item = new MenuItem("Exit");

            popup.add(item);

           trayIcon = new TrayIcon(image, "Anomaly Refresh by Schriever kommt", popup);
          
            ActionListener listener = new ActionListener() {               
                @Override
                public void actionPerformed(java.awt.event.ActionEvent event) {
                    
                    
                    System.exit(0);                 
                }               
            };                       

            ActionListener listenerTray = new ActionListener() {               
                @Override
                public void actionPerformed(java.awt.event.ActionEvent arg0) {
                    
                                System.out.println("Doppelklick!!!");
                                
                }                   
            };           

            trayIcon.addActionListener(listenerTray);
            item.addActionListener(listener);

            try{
              tray.add(trayIcon);
              trayIcon.displayMessage("Anomaly Refresh", "Die App wird im Hintergrund ausgeführt.", MessageType.INFO);
            
            }catch (Exception e) {
              System.err.println("Can't add to tray");
            }
          } else {
            System.err.println("Tray unavailable");
          }
        
    }

        
    
     @FXML protected void anleitungKlick(ActionEvent event) {
        //den Dialog erzeugen und anzeigen
            Alert meinDialog = new Alert(AlertType.INFORMATION, "Setzen sie im Informationskästchen den Haken, um eine wöchentliche Erneuerung der Anomaly-Database zu aktivieren.\nDieser Vorgang wird durch anklicken des Buttons ->jetzt Ausführen<- manuell gestartet.\nDurch klicken des Buttons ->Hintergrundmodus<- bleibt das Programm fortlaufend aktiv. Um eine korrekte Funktion zu gewährleisten, darf das Programm nicht geschlossen werden.");
            
            meinDialog.setTitle("Anleitung");
            //den Text setzen
            meinDialog.setHeaderText("Bitte beachten sie die folgenden Schritte:");
            //den Dialog anzeigen
            meinDialog.showAndWait();
     }
    
     @FXML protected void infoKlick(ActionEvent event) {
            //den Dialog erzeugen und anzeigen
                Alert meinDialog = new Alert(AlertType.INFORMATION, "Version 1.1\n© Oliver Schriever, 06/2020");
                
                meinDialog.setTitle("Info");
                //den Text setzen
                meinDialog.setHeaderText("Anomaly Refresh by Schrieverkommt");
                //den Dialog anzeigen
                meinDialog.showAndWait();
         }
    

    
    @FXML protected void aktivKlick(ActionEvent event) {
            Timer timer = new Timer();
            timer.scheduleAtFixedRate(new TimerTask() {
                
                @Override
                public void run() {
                    if (aktivBox.isSelected()) {
                    programmAusfuehren();
                    }
                    else {
                        timer.cancel();
            }
                    }
            }, 6*1000, 6*1000);
            
        
    
        
    }
    private void notification() {
        trayIcon.displayMessage("Anomaly Refresh by Schrieverkommt", "Die Anomaly Database wurde erneuert", MessageType.INFO);
    }
    
    @FXML protected void ausfuehrenKlick(ActionEvent event) {
        programmAusfuehren();
        
        
        
    }
    
     private void datumSetzen() {
          LocalDate date = LocalDate.now();
         String aktDatum;
           DateTimeFormatter df;
            df = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);      // Sonntag, 31. Januar 2016
          
            aktDatum = date.format(df);
            letzteAkt.setText(aktDatum);
        }
    private void programmAusfuehren() {
        Path anomalyOld = Paths.get("C:\\Users\\oschr\\Desktop\\Anomaly old\\Anomaly.DB");
        Path anomalyNew = Paths.get("C:\\Users\\oschr\\Desktop\\Anomaly new\\Anomaly.DB");
        
        
        try {
            Files.copy(anomalyOld, anomalyNew, StandardCopyOption.REPLACE_EXISTING);
            
            System.out.println("Kopie wurde erstellt");
            datumSetzen();
        } catch (Exception e) {
            e.printStackTrace();
            
        }
        
    }
    
}
 
L

lam_tr

Hier sogar ein lauffähiges Beispiel rauskopiert: https://stackoverflow.com/questions/12571329/javafx-app-in-system-tray

Code:
import java.awt.AWTException;
import java.awt.Image;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.URL;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class MainApp2 extends Application {

int stateWindow = 1;

@Override
public void start(final Stage stage) throws Exception {

//Check the SystemTray is supported
if (!SystemTray.isSupported()) {
    System.out.println("SystemTray is not supported");
    return;
}

URL url = System.class.getResource("/image/yourImage.png");
Image image = Toolkit.getDefaultToolkit().getImage(url);

//image dimensions must be 16x16 on windows, works for me
final TrayIcon trayIcon = new TrayIcon(image, "application name");

final SystemTray tray = SystemTray.getSystemTray();

//Listener left clic XD
trayIcon.addMouseListener(new MouseAdapter() {
    @Override
    public void mouseClicked(MouseEvent event) {
        if (event.getButton() == MouseEvent.BUTTON1) {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    if (stateWindow == 1) {
                        stage.hide();
                        stateWindow = 0;
                    } else if (stateWindow == 0) {
                        stage.show();
                        stateWindow = 1;
                    }
                }
            });
        }

    }
});

try {
    tray.add(trayIcon);
} catch (AWTException e) {
    System.out.println("TrayIcon could not be added.");
}

stage.setTitle("Hello man!");
Button btn = new Button();
btn.setText("Say 'Hello man'");
btn.setOnAction(new EventHandler<ActionEvent>() {

    @Override
    public void handle(ActionEvent event) {
        System.out.println("Hello man!");
    }
});
StackPane root = new StackPane();
root.getChildren().add(btn);
stage.setScene(new Scene(root, 300, 250));
Platform.setImplicitExit(false);
stage.show();

}

/**
 * The main() method is ignored in correctly deployed JavaFX application.
 * main() serves only as fallback in case the application can not be
 * launched through deployment artifacts, e.g., in IDEs with limited FX
 * support. NetBeans ignores main().
 *
 * @param args the command line arguments
 */
public static void main(String[] args) {
launch(args);
}
}
 
OSchriever

OSchriever

Ich habe den MouseListener bei mir eingefügt, passiert auch nichts wenn man auf das Icon klickt. Hier der geänderte Code.
Irgendwie hat das noch nichts gebracht.


Java:
package de.schrieverkommt;


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.TrayIcon.MessageType;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Timer;
import java.util.TimerTask;
import com.sun.nio.sctp.Notification;

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;




public class FXMLController {
    
    @FXML private CheckBox aktivBox;
    @FXML private Label letzteAkt;
    @FXML private Button ausfuehren;
    @FXML private Button anleitung;
    @FXML private Button info;
    @FXML private Button hintergrund;
    @FXML private Pane pane;
    
    TrayIcon trayIcon;
    int stateWindow = 0;
    
    @FXML protected void hintergrundKlick(ActionEvent event) {
        
        Stage stage =(Stage)pane.getScene().getWindow();
        stage.hide();
        
        
        if (SystemTray.isSupported()) {         
            SystemTray tray = SystemTray.getSystemTray();
            Image image = Toolkit.getDefaultToolkit().getImage("C:\\Users\\oschr\\Desktop\\aa.png");
            PopupMenu popup = new PopupMenu();
            MenuItem item = new MenuItem("Exit");

            popup.add(item);

           trayIcon = new TrayIcon(image, "Anomaly Refresh by Schriever kommt", popup);
          
            ActionListener listener = new ActionListener() {               
                @Override
                public void actionPerformed(java.awt.event.ActionEvent event) {
                    
                    
                    System.exit(0);                 
                }               
            };
            
            
            

            trayIcon.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent event) {
                    if (event.getButton() == MouseEvent.BUTTON1) {
                        Platform.runLater(new Runnable() {
                            @Override
                            public void run() {
                                if (stateWindow == 1) {
                                    stage.hide();
                                    stateWindow = 0;
                                } else if (stateWindow == 0) {
                                    stage.show();
                                    stateWindow = 1;
                                }
                            }
                        });
                    }

                }
            });
            
        
//            ActionListener listenerTray = new ActionListener() {               
//                @Override
//                public void actionPerformed(java.awt.event.ActionEvent arg0) {
//                   
//                                System.out.println("Doppelklick!!!");
//                               
//                }                   
//            };           

//            trayIcon.addActionListener(listenerTray);
            item.addActionListener(listener);

            try{
              tray.add(trayIcon);
              trayIcon.displayMessage("Anomaly Refresh", "Die App wird im Hintergrund ausgeführt.", MessageType.INFO);
            
            }catch (Exception e) {
              System.err.println("Can't add to tray");
            }
          } else {
            System.err.println("Tray unavailable");
          }
        
    
    
    
    
    
    }
    
    
    
    
    
    
    
    
    
    
    
    

        
    
     @FXML protected void anleitungKlick(ActionEvent event) {
        //den Dialog erzeugen und anzeigen
            Alert meinDialog = new Alert(AlertType.INFORMATION, "Setzen sie im Informationskästchen den Haken, um eine wöchentliche Erneuerung der Anomaly-Database zu aktivieren.\nDieser Vorgang wird durch anklicken des Buttons ->jetzt Ausführen<- manuell gestartet.\nDurch klicken des Buttons ->Hintergrundmodus<- bleibt das Programm fortlaufend aktiv. Um eine korrekte Funktion zu gewährleisten, darf das Programm nicht geschlossen werden.");
            
            meinDialog.setTitle("Anleitung");
            //den Text setzen
            meinDialog.setHeaderText("Bitte beachten sie die folgenden Schritte:");
            //den Dialog anzeigen
            meinDialog.showAndWait();
     }
    
     @FXML protected void infoKlick(ActionEvent event) {
            //den Dialog erzeugen und anzeigen
                Alert meinDialog = new Alert(AlertType.INFORMATION, "Version 1.1\n© Oliver Schriever, 06/2020");
                
                meinDialog.setTitle("Info");
                //den Text setzen
                meinDialog.setHeaderText("Anomaly Refresh by Schrieverkommt");
                //den Dialog anzeigen
                meinDialog.showAndWait();
         }
    

    
    @FXML protected void aktivKlick(ActionEvent event) {
            Timer timer = new Timer();
            timer.scheduleAtFixedRate(new TimerTask() {
                
                @Override
                public void run() {
                    if (aktivBox.isSelected()) {
                    programmAusfuehren();
                    }
                    else {
                        timer.cancel();
            }
                    }
            }, 6*1000, 6*1000);
            
        
    
        
    }
    private void notification() {
        trayIcon.displayMessage("Anomaly Refresh by Schrieverkommt", "Die Anomaly Database wurde erneuert", MessageType.INFO);
    }
    
    @FXML protected void ausfuehrenKlick(ActionEvent event) {
        programmAusfuehren();
        
        
        
    }
    
     private void datumSetzen() {
          LocalDate date = LocalDate.now();
         String aktDatum;
           DateTimeFormatter df;
            df = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);      // Sonntag, 31. Januar 2016
          
            aktDatum = date.format(df);
            letzteAkt.setText(aktDatum);
        }
    private void programmAusfuehren() {
        Path anomalyOld = Paths.get("C:\\Users\\oschr\\Desktop\\Anomaly old\\Anomaly.DB");
        Path anomalyNew = Paths.get("C:\\Users\\oschr\\Desktop\\Anomaly new\\Anomaly.DB");
        
        
        try {
            Files.copy(anomalyOld, anomalyNew, StandardCopyOption.REPLACE_EXISTING);
            
            System.out.println("Kopie wurde erstellt");
            datumSetzen();
        } catch (Exception e) {
            e.printStackTrace();
            
        }
        
    }
    
}
Platform.runLater(e-> stage.show()) habe ich vorher auch schon probiert. Kann es was damit zu tun haben, dass ich mich ja in der Controller-Klasse befinde? Die Beispiele arbeiten ja alle aus der Main-Klasse heraus.
Aber ich wüsste nicht, wie ich das in die Main-Klasse programmieren soll.
Da ich noch Anfänger bin, brauche ich leider etwas Rückenwind. :)
Vielen Dank
 
L

lam_tr

Ich habe den MouseListener bei mir eingefügt, passiert auch nichts wenn man auf das Icon klickt. Hier der geänderte Code.
Irgendwie hat das noch nichts gebracht.


Java:
package de.schrieverkommt;


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.TrayIcon.MessageType;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Timer;
import java.util.TimerTask;
import com.sun.nio.sctp.Notification;

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;




public class FXMLController {
   
    @FXML private CheckBox aktivBox;
    @FXML private Label letzteAkt;
    @FXML private Button ausfuehren;
    @FXML private Button anleitung;
    @FXML private Button info;
    @FXML private Button hintergrund;
    @FXML private Pane pane;
   
    TrayIcon trayIcon;
    int stateWindow = 0;
   
    @FXML protected void hintergrundKlick(ActionEvent event) {
       
        Stage stage =(Stage)pane.getScene().getWindow();
        stage.hide();
       
       
        if (SystemTray.isSupported()) {        
            SystemTray tray = SystemTray.getSystemTray();
            Image image = Toolkit.getDefaultToolkit().getImage("C:\\Users\\oschr\\Desktop\\aa.png");
            PopupMenu popup = new PopupMenu();
            MenuItem item = new MenuItem("Exit");

            popup.add(item);

           trayIcon = new TrayIcon(image, "Anomaly Refresh by Schriever kommt", popup);
         
            ActionListener listener = new ActionListener() {              
                @Override
                public void actionPerformed(java.awt.event.ActionEvent event) {
                   
                   
                    System.exit(0);                
                }              
            };
           
           
           

            trayIcon.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent event) {
                    if (event.getButton() == MouseEvent.BUTTON1) {
                        Platform.runLater(new Runnable() {
                            @Override
                            public void run() {
                                if (stateWindow == 1) {
                                    stage.hide();
                                    stateWindow = 0;
                                } else if (stateWindow == 0) {
                                    stage.show();
                                    stateWindow = 1;
                                }
                            }
                        });
                    }

                }
            });
           
       
//            ActionListener listenerTray = new ActionListener() {              
//                @Override
//                public void actionPerformed(java.awt.event.ActionEvent arg0) {
//                  
//                                System.out.println("Doppelklick!!!");
//                              
//                }                  
//            };          

//            trayIcon.addActionListener(listenerTray);
            item.addActionListener(listener);

            try{
              tray.add(trayIcon);
              trayIcon.displayMessage("Anomaly Refresh", "Die App wird im Hintergrund ausgeführt.", MessageType.INFO);
           
            }catch (Exception e) {
              System.err.println("Can't add to tray");
            }
          } else {
            System.err.println("Tray unavailable");
          }
       
   
   
   
   
   
    }
   
   
   
   
   
   
   
   
   
   
   
   

       
   
     @FXML protected void anleitungKlick(ActionEvent event) {
        //den Dialog erzeugen und anzeigen
            Alert meinDialog = new Alert(AlertType.INFORMATION, "Setzen sie im Informationskästchen den Haken, um eine wöchentliche Erneuerung der Anomaly-Database zu aktivieren.\nDieser Vorgang wird durch anklicken des Buttons ->jetzt Ausführen<- manuell gestartet.\nDurch klicken des Buttons ->Hintergrundmodus<- bleibt das Programm fortlaufend aktiv. Um eine korrekte Funktion zu gewährleisten, darf das Programm nicht geschlossen werden.");
           
            meinDialog.setTitle("Anleitung");
            //den Text setzen
            meinDialog.setHeaderText("Bitte beachten sie die folgenden Schritte:");
            //den Dialog anzeigen
            meinDialog.showAndWait();
     }
   
     @FXML protected void infoKlick(ActionEvent event) {
            //den Dialog erzeugen und anzeigen
                Alert meinDialog = new Alert(AlertType.INFORMATION, "Version 1.1\n© Oliver Schriever, 06/2020");
               
                meinDialog.setTitle("Info");
                //den Text setzen
                meinDialog.setHeaderText("Anomaly Refresh by Schrieverkommt");
                //den Dialog anzeigen
                meinDialog.showAndWait();
         }
   

   
    @FXML protected void aktivKlick(ActionEvent event) {
            Timer timer = new Timer();
            timer.scheduleAtFixedRate(new TimerTask() {
               
                @Override
                public void run() {
                    if (aktivBox.isSelected()) {
                    programmAusfuehren();
                    }
                    else {
                        timer.cancel();
            }
                    }
            }, 6*1000, 6*1000);
           
       
   
       
    }
    private void notification() {
        trayIcon.displayMessage("Anomaly Refresh by Schrieverkommt", "Die Anomaly Database wurde erneuert", MessageType.INFO);
    }
   
    @FXML protected void ausfuehrenKlick(ActionEvent event) {
        programmAusfuehren();
       
       
       
    }
   
     private void datumSetzen() {
          LocalDate date = LocalDate.now();
         String aktDatum;
           DateTimeFormatter df;
            df = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);      // Sonntag, 31. Januar 2016
         
            aktDatum = date.format(df);
            letzteAkt.setText(aktDatum);
        }
    private void programmAusfuehren() {
        Path anomalyOld = Paths.get("C:\\Users\\oschr\\Desktop\\Anomaly old\\Anomaly.DB");
        Path anomalyNew = Paths.get("C:\\Users\\oschr\\Desktop\\Anomaly new\\Anomaly.DB");
       
       
        try {
            Files.copy(anomalyOld, anomalyNew, StandardCopyOption.REPLACE_EXISTING);
           
            System.out.println("Kopie wurde erstellt");
            datumSetzen();
        } catch (Exception e) {
            e.printStackTrace();
           
        }
       
    }
   
}
Platform.runLater(e-> stage.show()) habe ich vorher auch schon probiert. Kann es was damit zu tun haben, dass ich mich ja in der Controller-Klasse befinde? Die Beispiele arbeiten ja alle aus der Main-Klasse heraus.
Aber ich wüsste nicht, wie ich das in die Main-Klasse programmieren soll.
Da ich noch Anfänger bin, brauche ich leider etwas Rückenwind. :)
Vielen Dank

Kommst du in diese Methode überhaupt rein wenn du den TrayIcon anklickst? Debug mal darein

Code:
trayIcon.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent event) {
                    if (event.getButton() == MouseEvent.BUTTON1) {
                        Platform.runLater(new Runnable() {
                            @Override
                            public void run() {
                                if (stateWindow == 1) {
                                    stage.hide();
                                    stateWindow = 0;
                                } else if (stateWindow == 0) {
                                    stage.show();
                                    stateWindow = 1;
                                }
                            }
                        });
                    }

                }
            });
 
OSchriever

OSchriever

Jupp hab ich angepasst und auch die Größe vom Bild auf 16x16 gesetzt. Hab trotzdem nen Fehler in der Zeile 33:
at java.desktop/sun.awt.SunToolkit.getImage(Unknown Source)
at Main.start(Main.java:33)

Dann versuche ich es nachher mal mit dem Debugger.
 
J

JustNobody

Was hast Du denn da angegeben? Du hast gesehen, dass er System.class.getResource aufruft, d.h. er geht über den Classloader. Also mit Deiner Angabe ganzer Pfade kann er da nichts laden!

Die Bilder gehören als Ressource ins Projekt und dann müssen diese entsprechend geladen werden.
 
L

lam_tr

Für alle die an das Problem interessiert sind. Wir haben es gelöst.

Damit die Anwendung nicht wirklick komplett geschlossen wird, muss in der Application Klasse Platform.setImplicitExit(false); aufgerufen werden.
 
OSchriever

OSchriever

Hi, alles läuft gut, jedoch werden die Bilder nach dem Exportieren nicht angezeigt. Da habe ich 1x ein Bild(Firmenlogo) das ich im SceneBuilder eingefügt habe und dort auch die Url angegeben habe. Im Bereich Code habe ich nichts weiter eingegeben(siehe Screenshot).
Dann habe ich noch das Icon im SystemTray. Beide Bilder sind in einem Ordner Icons im Projekt. Ich füge hier nochmal den Code an sowie ein paar Screenshots.
Vielleicht hat ja jemand eine Idee wo das dran liegen könnte...
LG



Anmerkung 2020-06-28 204906.jpgAnmerkung 2020-06-28 204925.jpg Anmerkung 2020-06-28 204830.jpg


Java:
package de.schrieverkommt;

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.TrayIcon.MessageType;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Timer;
import java.util.TimerTask;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class FXMLController {

    @FXML
    private CheckBox aktivBox;
    @FXML
    private Label letzteAkt;
    @FXML
    private Button ausfuehren;
    @FXML
    private Button anleitung;
    @FXML
    private Button info;
    @FXML
    private Button hintergrund;
    @FXML
    private Pane pane;
    
    TrayIcon trayIcon;
    int stateWindow = 0;
    
    @FXML
    protected void hintergrundKlick(ActionEvent event) {
        //Die Stage der Mainklasse holen
        Stage stage = (Stage) pane.getScene().getWindow();
        //Die Applikation in den Hintergrund setzen
        stage.hide();
        //Das Symbol im Systemtray
        if (SystemTray.isSupported()) {
            SystemTray tray = SystemTray.getSystemTray();
            Image image = Toolkit.getDefaultToolkit().getImage("icons/icon.png");
            PopupMenu popup = new PopupMenu();
            //Schließen-Symbol setzen
            MenuItem item = new MenuItem("Exit");
            
            popup.add(item);
            //Popup-Text setzen
            trayIcon = new TrayIcon(image, "Anomaly Refresh by Schriever kommt", popup);

            ActionListener listener = new ActionListener() {
                
                //Der Listener zum Schließen der Anwendung
                @Override
                public void actionPerformed(java.awt.event.ActionEvent event) {

                    System.exit(0);
                }
            };
            //Der Listener zum Anzeigen/Verstecken bei Klick auf das System-Tray Symbol
            trayIcon.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent event) {
                    if (event.getButton() == MouseEvent.BUTTON1) {
                        Platform.runLater(new Runnable() {
                            @Override
                            public void run() {
                                if (stateWindow == 1) {
                                    stage.hide();
                                    stateWindow = 0;
                                } else if (stateWindow == 0) {
                                    stage.show();
                                    stateWindow = 1;
                                }
                            }
                        });
                    }

                }
            });

            item.addActionListener(listener);

            try {
                tray.add(trayIcon);
                trayIcon.displayMessage("Anomaly Refresh", "Die App wird im Hintergrund ausgeführt.", MessageType.INFO);

            } catch (Exception e) {
                System.err.println("Can't add to tray");
            }
        } else {
            System.err.println("Tray unavailable");
        }

    }
    //Die Anleitung anzeigen
    @FXML
    protected void anleitungKlick(ActionEvent event) {
        // den Dialog erzeugen und anzeigen
        Alert meinDialog = new Alert(AlertType.INFORMATION,
                "Setzen sie im Informationskästchen den Haken, um eine wöchentliche Erneuerung der Anomaly-Database zu aktivieren.\nDieser Vorgang wird durch anklicken des Buttons ->jetzt Ausführen<- manuell gestartet.\nDurch klicken des Buttons ->Hintergrundmodus<- bleibt das Programm fortlaufend aktiv. Um eine korrekte Funktion zu gewährleisten, darf das Programm nicht geschlossen werden.");

        meinDialog.setTitle("Anleitung");
        // den Text setzen
        meinDialog.setHeaderText("Bitte beachten sie die folgenden Schritte:");
        // den Dialog anzeigen
        meinDialog.showAndWait();
    }
    //Die Informationen anzeigen
    @FXML
    protected void infoKlick(ActionEvent event) {
        // den Dialog erzeugen und anzeigen
        Alert meinDialog = new Alert(AlertType.INFORMATION, "Version 1.1\n© Oliver Schriever, 06/2020");

        meinDialog.setTitle("Info");
        // den Text setzen
        meinDialog.setHeaderText("Anomaly Refresh by Schrieverkommt");
        // den Dialog anzeigen
        meinDialog.showAndWait();
    }
    
    //Das Zeit-Programm laufen lassen
    @FXML
    protected void aktivKlick(ActionEvent event) {
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {

            @Override
            public void run() {
                if (aktivBox.isSelected()) {
                    programmAusfuehren();
                    notification();
                } else {
                    timer.cancel();
                }
            }
            //Die Verzögerungszeit sowie die Intervallzeit für das Starten der Anwendung in Milisekunden. Hier 1 Monat
        }, 2628 * 1000, 2628 * 1000);

    }
    //Benachrichtigung wenn die Database erneuert wurde
    private void notification() {
        trayIcon.displayMessage("Anomaly Refresh by Schrieverkommt", "Die Anomaly Database wurde erneuert",
                MessageType.INFO);
    }
    //Button Ausführen wurde geklickt
    @FXML
    protected void ausfuehrenKlick(ActionEvent event) {
        programmAusfuehren();

    }
    //Das Datum der letzten Ausführung im Label setzen
    private void datumSetzen() {
        LocalDate date = LocalDate.now();
        String aktDatum;
        DateTimeFormatter df;
        df = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL); // Sonntag, 31. Januar 2016

        aktDatum = date.format(df);
        letzteAkt.setText(aktDatum);
    }
    //Das Kopieren der Dateien
    private void programmAusfuehren() {
        Path anomalyOld = Paths.get("C:\\Program Files\\Dairymaster\\Dmmwin\\Data\\Anomaly.DB");
        Path anomalyNew = Paths.get("C:\\Program Files\\Dairymaster\\Schriever kommt\\Anomaly new\\Anomaly.DB");
        
        //Die Datei wird ersetzt!
        try {
            Files.copy(anomalyNew, anomalyOld, StandardCopyOption.REPLACE_EXISTING);

            
            datumSetzen();
        } catch (Exception e) {
            
            Alert meinDialog = new Alert(AlertType.ERROR,e.toString());
                    

            meinDialog.setTitle("Fehler!");
            // den Text setzen
            meinDialog.setHeaderText("Die Datenbank wurde nicht gefunden:");
            // den Dialog anzeigen
            meinDialog.showAndWait();
            
            
            

        }

    }

}
Java:
package de.schrieverkommt;


import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;


public class Main extends Application {

    
    @Override
    public void start(Stage meineStage) throws Exception {
        
        Parent root = FXMLLoader.load(getClass().getResource("sb_AnomalyRefresh.fxml"));
        
        
        
        Scene meineScene = new Scene(root, 656, 500);
        
        //den Titel über stage setzen
        meineStage.setTitle("Anomaly Refresh by Schrieverkommt");
        
        
        //die Szene setzen
        meineStage.setScene(meineScene);
        //Muss gesetzt werden, da die Anwendung nur versteckt werden soll, kann sonst mit der Anweisung stage.show() nicht wieder geholt werden
        Platform.setImplicitExit(false);
        
        meineStage.show();
        
    }
    
    
    

    public static void main(String[] args) {
        launch(args);

        
        


    }
    

    

}
 
L

lam_tr

Ich vermute mal dass diese Icons beim Exportieren nicht mit geliefert sind. Das kannst du sehr schnell testen indem du die Jar exportierst und danach suchst.
 
OSchriever

OSchriever

Die sind im Ordner icons mit drin. (Siehe Screenshot)Anmerkung 2020-07-01 125634.png

Vom Code her müsste das doch eigentlich funktionieren? 😏
 
L

lam_tr

Versuche in der fxml nicht das Icon Verzeichnis nicht mit ../../../logo.png zu machen, stattdessen /icons/logo.png
 
J

JustNobody

Wie lädst Du das Image? Ist es diese Zeile:
Image image = Toolkit.getDefaultToolkit().getImage("icons/icon.png");

Das Toolkit will eine Datei laden. Das ist also kein laden einer Ressource aus dem jar (So wie ich das Verstehe. Siehe: https://docs.oracle.com/javase/9/docs/api/java/awt/Toolkit.html#getImage-java.lang.String-)

Daher solltest Du ggf. explizit die Ressource laden. Dazu könnte ein Code wie:
Image image = Toolkit.getDefaultToolkit().getImage(getClass.getResource("/icons/icon.png"));
brauchbar sein.

Aber auch hier ist dann wichtig: Gib das icon absolut an, wie es auf dem Classpath zu finden ist!

Edit: Aber ich muss auch ehrlich zugeben, dass mir das mit der Auswahl in der GUI nicht ganz verständlich wird. Das wäre dann ja auch nur eine Auswahl im Filesystem und nicht im Jar ...
 
L

lam_tr

Wie lädst Du das Image? Ist es diese Zeile:
Image image = Toolkit.getDefaultToolkit().getImage("icons/icon.png");

Das Toolkit will eine Datei laden. Das ist also kein laden einer Ressource aus dem jar (So wie ich das Verstehe. Siehe: https://docs.oracle.com/javase/9/docs/api/java/awt/Toolkit.html#getImage-java.lang.String-)

Daher solltest Du ggf. explizit die Ressource laden. Dazu könnte ein Code wie:
Image image = Toolkit.getDefaultToolkit().getImage(getClass.getResource("/icons/icon.png"));
brauchbar sein.

Aber auch hier ist dann wichtig: Gib das icon absolut an, wie es auf dem Classpath zu finden ist!

Edit: Aber ich muss auch ehrlich zugeben, dass mir das mit der Auswahl in der GUI nicht ganz verständlich wird. Das wäre dann ja auch nur eine Auswahl im Filesystem und nicht im Jar ...
Es geht hier mehr um die Image die im FXML definiert ist. Das Iconsverzeichnis liegt im Classpath von daher kann man dann direkt /icons/logo.jpg daraufzugreifen.
 
OSchriever

OSchriever

Wie lädst Du das Image? Ist es diese Zeile:
Image image = Toolkit.getDefaultToolkit().getImage("icons/icon.png");
Jupp genau.
Daher solltest Du ggf. explizit die Ressource laden. Dazu könnte ein Code wie:
Image image = Toolkit.getDefaultToolkit().getImage(getClass.getResource("/icons/icon.png"));
brauchbar sein.
Dann kann er mit getClass.getResource nichts anfangen.
Edit: Aber ich muss auch ehrlich zugeben, dass mir das mit der Auswahl in der GUI nicht ganz verständlich wird. Das wäre dann ja auch nur eine Auswahl im Filesystem und nicht im Jar ...
Wie meinst du das? 🧐
 
OSchriever

OSchriever

Versuche in der fxml nicht das Icon Verzeichnis nicht mit ../../../logo.png zu machen, stattdessen /icons/logo.png
Das funktioniert nicht, dann findet er das Bild im Scenebuilder nicht mehr. Selbst wenn ich das im SB manuell so ändere, dann wird der Pfad vom SB wieder auf das ursprüngliche geändert. Wenn ich das dann in der FXML ändere dann findet er das Bild nicht mehr...
 
J

JustNobody

Bei getClass fehlten die Klammern ... das ist natürlich eine Methode. Das ist halt blöd, wenn man so Code direkt im Forum schreibt.
 
Thema: 

Anwendung aus SystemTray öffnen

Passende Stellenanzeigen aus deiner Region:
Anzeige

Neue Themen

Anzeige

Anzeige
Oben