2015-12-08 1 views
0

Mon code lit actuellement ma boîte de réception Gmail via IMAP (imaps) et javamail, et une fois qu'il trouve un email avec une pièce jointe zip/xap, il affiche une scène demandant si le fichier, oui ou non.Gérer plusieurs lancements d'applications JavaFX dans une boucle

Je souhaite que la scène se ferme une fois que j'ai fait une sélection, puis revenez à l'endroit dans la boucle d'où provient l'appel. Mon problème se pose parce que vous ne pouvez pas lancer une application plus d'une fois, donc je lis here que je devrais écrire Platform.setImplicitExit(false); dans la méthode start, puis utiliser primartyStage.hide() (?) Et puis quelque chose comme Platform.runLater(() -> primaryStage.show()); quand j'ai besoin d'afficher la scène plus tard.

Le problème qui se pose maintenant est que le flux de commande commence dans la méthode doit() de Mail.java qui boucle dans ma boîte de réception, et launch(args) se produit dans un for loop dans la méthode. Cela signifie launch(args) puis appelle start pour définir la scène et afficher la scène. Comme Controller.java et fxml sont associés, la classe Controller a un gestionnaire d'événement pour les boutons de la scène qui "interceptent" le flux une fois que start a montré la scène. Par conséquent, quand je clique sur Oui ou Non, il cache la scène, mais juste se bloque là. Comme s'il ne pouvait pas retourner à la méthode start pour continuer la boucle d'où le lancement (args) s'est produit. Comment puis-je correctement masquer/montrer la scène chaque fois que nécessaire, permettant à la boucle de continuer si oui ou non a été cliqué.

Voici le code pour Mail.java et Controller.java. Merci beaucoup!

Mail.java

[Other variables set here] 
    public static int launchCount = 0;@FXML public Text subjectHolder; 

    public static ReceiveMailImap obj = new ReceiveMailImap(); 

    public static void main(String[] args) throws IOException,  MessagingException { 
     ReceiveMailImap.doit(); 
    } 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     loader = new FXMLLoader(getClass().getResource("prompts.fxml")); 
     root = loader.load(); 
     controller = loader.getController(); 
     controller.setPrimaryStage(primaryStage); 
     scene = new Scene(root, 450, 250); 
     controller.setPrimaryScene(scene); 
     scene.getStylesheets().add("styleMain.css"); 
     Platform.setImplicitExit(false); 
     primaryStage.setTitle("Download this file?"); 
     primaryStage.initStyle(StageStyle.UNDECORATED); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    public static void doit() throws MessagingException, IOException { 
     Folder inbox = null; 
     Store store = null; 

     try { 
      Properties props = System.getProperties(); 
      Session session = Session.getDefaultInstance(props, null); 
      store = session.getStore("imaps"); 
      store.connect("imap.gmail.com", "[email protected]", "Password"); 
      inbox = store.getFolder("Inbox"); 
      inbox.open(Folder.READ_WRITE); 
      Message[] messages = inbox.getMessages(); 
      FetchProfile fp = new FetchProfile(); 
      fp.add(FetchProfile.Item.ENVELOPE); 
      fp.add(UIDFolder.FetchProfileItem.FLAGS); 
      fp.add(UIDFolder.FetchProfileItem.CONTENT_INFO); 
      fp.add("X-mailer"); 

      inbox.fetch(messages, fp); 
      int doc = 0; 
      int maxDocs = 400; 
      for (int i = messages.length - 1; i >= 0; i--) { 
       Message message = messages[i]; 
       if (doc < maxDocs) { 
        doc++; 
        message.getSubject(); 

        if (!hasAttachments(message)) { 
         continue; 
        } 
        String from = "Sender Unknown"; 
        if (message.getReplyTo().length >= 1) { 
         from = message.getReplyTo()[0].toString(); 
        } else if (message.getFrom().length >= 1) { 
         from = message.getFrom()[0].toString(); 
        } 
        subject = message.getSubject(); 
        if (from.contains("[email protected]")) { 
         saveAttachment(message.getContent()); 
         message.setFlag(Flags.Flag.SEEN, true); 
        } 
       } 
      } 
     } finally { 
      if (inbox != null) { 
       inbox.close(true); 
      } 
      if (store != null) { 
       store.close(); 
      } 
     } 
    } 

    public static boolean hasAttachments(Message msg) throws MessagingException, IOException { 
     if (msg.isMimeType("multipart/mixed")) { 
      Multipart mp = (Multipart) msg.getContent(); 
      if (mp.getCount() > 1) return true; 
     } 
     return false; 
    } 

    public static void saveAttachment(Object content) 
    throws IOException, MessagingException { 
     out = null; in = null; 
     try { 
      if (content instanceof Multipart) { 
       Multipart multi = ((Multipart) content); 
       parts = multi.getCount(); 
       for (int j = 0; j < parts; ++j) { 
        part = (MimeBodyPart) multi.getBodyPart(j); 
        if (part.getContent() instanceof Multipart) { 
         // part-within-a-part, do some recursion... 
         saveAttachment(part.getContent()); 
        } else { 
         int allow = 0; 
         if (part.isMimeType("application/x-silverlight-app")) { 
          extension = "xap"; 
          allow = 1; 
         } else { 
          extension = "zip"; 
          allow = 1; 
         } 
         if (allow == 1) { 
          if (launchCount == 0) { 
           launch(args); 
           launchCount++; 
          } else { 
           Platform.runLater(() -> primaryStage.show()); 
          } 
         } else { 
          continue; 
         } 
        } 
       } 
      } 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } finally { 
      if (in != null) { in .close(); 
      } 
      if (out != null) { 
       out.flush(); 
       out.close(); 
      } 
     } 
    } 

    public static File createFolder(String subject) { 
     JFileChooser fr = new JFileChooser(); 
     FileSystemView myDocs = fr.getFileSystemView(); 
     String myDocuments = myDocs.getDefaultDirectory().toString(); 
     dir = new File(myDocuments + "\\" + subject); 
     savePathNoExtension = dir.toString(); 
     dir.mkdir(); 
     System.out.println("Just created: " + dir); 
     return dir; 
    } 

} 

Controller.java

public class Controller implements Initializable { 

    @FXML 
    private Text subjectHolder; 
    public Button yesButton, noButton; 
    public ReceiveMailImap subject; 

    @Override 
    public void initialize(URL url, ResourceBundle rb) { 
     subject= new ReceiveMailImap(); 
     subjectHolder.setText(subject.returnSubject()); 
    } 
    public Stage primaryStage; 
    public Scene scene; 

    @FXML 
    ComboBox<String> fieldCombo; 

    public void setPrimaryStage(Stage stage) { 
     this.primaryStage = stage; 
    } 

    public void setPrimaryScene(Scene scene) { 
     this.scene = scene; 
    } 

    public String buttonPressed(ActionEvent e) throws IOException, MessagingException { 
     Object source = e.getSource(); 
     if(source==yesButton){ 
      System.out.println("How to tell Mail.java that user clicked Yes?"); 
      return "POSITIVE";} 
     else{subject.dlOrNot("no"); 
      System.out.println("How to tell Mail.java that user clicked No?"); 
      primaryStage.hide(); 
      return "NEGATIVE";} 
    } 

} 

Répondre

2

Il y a beaucoup de problèmes avec le code que vous avez posté, mais laissez-moi juste essayer d'aborder les vous posez des questions sur.

La raison pour laquelle le code se bloque est que Application.launch(...)

ne renvoie pas tant que l'application a quitté

En général, vous avez mal compris type de l'ensemble du cycle de vie d'une application JavaFX ici. Vous devriez considérer la méthode start(...) comme l'équivalent de la méthode main(...) dans une application Java "traditionnelle". La seule chose à savoir est que start(...) est exécuté sur le thread d'application FX, donc si vous devez exécuter un code de blocage, vous devez le mettre dans un thread d'arrière-plan.

La méthode start(...) reçoit une instance Stage pour plus de commodité, car la chose la plus courante consiste à créer un graphique de scène et à l'afficher dans une scène. Vous n'êtes cependant pas obligé d'utiliser cette étape, vous pouvez l'ignorer et créer vos propres étapes au fur et à mesure de vos besoins.

Je pense que vous pouvez essentiellement structurer votre code comme suit (bien que, pour être honnête, j'ai beaucoup de mal à comprendre ce que vous faites):

public class Mail extends Application { 

    @Override 
    public void start(Stage ignored) throws Exception { 

     Platform.setImplicitExit(false); 

     Message[] messages = /* retrieve messages */ ; 
     for (Message message : messages) { 
      if (/* need to display window */) { 
       showMessage(message); 
      } 
     } 
    } 

    private void showMessage(Message message) { 
     FXMLLoader loader = new FXMLLoader(getClass().getResource("prompts.fxml")); 
     Parent root = loader.load(); 

     Controller controller = loader.getController(); 
     Scene scene = new Scene(root, 450, 250); 
     stage.setScene(scene); 
     stage.initStyle(StageStyle.UNDECORATED); 
     stage.setTitle(...); 

     // showAndWait will block execution until the window is hidden, so 
     // you can query which button was pressed afterwards: 

     stage.showAndWait(); 

     if (controller.wasYesPressed()) { 
      // ... 
     } 
    } 

    // for IDEs that don't support directly launching a JavaFX Application: 
    public static void main(String[] args) { 
     launch(args); 
    } 
} 

Il est évident que votre logique pour décider si la montrer une fenêtre est plus complexe, mais cela vous donnera la structure de base.

Pour vérifier quel bouton a été pressé, utilisez showAndWait comme ci-dessus et dans votre contrôleur faire

public class Controller { 

    @FXML 
    private Button yesButton ; 

    private boolean yesButtonPressed = false ; 

    public boolean wasYesPressed() { 
     return yesButtonPressed ; 
    } 

    // use different handlers for different buttons: 
    @FXML 
    private void yesButtonPressed() { 
     yesButtonPressed = true ; 
     closeWindow(); 
    } 

    @FXML 
    private void noButtonPressed() { 
     yesButtonPressed = false ; // not really needed, but makes things clearer 
     closeWindow(); 
    } 

    private void closeWindow() { 
     // can use any @FXML-injected node here: 
     yesButton.getScene().getWindow().hide(); 
    } 
} 
+0

!! Résolu James, merci beaucoup! Vous avez fourni juste assez de détails pour que je puisse résoudre les problèmes avec mon code et répondre à ma question principale. J'ai beaucoup appris de votre message. Très apprécié! Prends soin. –