2010-11-12 5 views
2

L'application Java WebStart sur laquelle je travaille utilise SWT pour l'interface graphique, et j'ai récemment réalisé un problème petit mais ennuyeux. Lorsque je choisis une action qui utilise un FileDialog, c'est-à-dire enregistrer l'image, l'interface utilisateur se bloque immédiatement après la fermeture de la boîte de dialogue. L'image est enregistrée et peut être ouverte avec une visionneuse d'images par défaut sans aucun problème, mais l'application n'est plus réactive à partir de ce moment, et je suis obligée de tuer l'application.SWT bloque/se bloque sur Linux, lors du déploiement en tant que Java Web Start

J'ai remarqué que le résultat est le même quand essayer d'ouvrir un fichier en utilisant un FileDialog, si je préfère ouvrir le même fichier en l'envoyant comme argument en utilisant le fichier jnlp, ça marche bien, donc je ne sais pas pense que c'est un problème avec le système de fichiers local.

J'ai essayé de reproduire le problème sur Windows seulement pour voir que cela fonctionne bien sur Win 7. Comme une deuxième tentative de dépannage, j'ai essayé de sauvegarder une image de la version locale de l'application (en d'autres termes, non -JWS) et ça fonctionne bien aussi ...

Je suspectais un problème d'autorisations sur le fichier jnlp, mais toutes les permissions sont données à l'application, et les signatures sont toutes ok aussi (le fait que l'application commence points à cela). D'ailleurs le fichier image est écrit de toute façon, donc ça ne peut pas vraiment être une chose de permission.

Des idées?

MISE À JOUR: Apparemment, le problème ne dépend pas uniquement de FileDialog, mais de n'importe quel type d'interaction utilisateur graphique. Chaque fois que des fenêtres SWT sont déployées, le programme se fige avec un écran gris, APRÈS n'importe quelle action qui était supposée être faite. J'ai copié du code ci-dessous, dans cet exemple particulier même si je clique sur Annuler, l'application devient non réactive avec un écran gris. Voici quelques exemples de code:

public static boolean saveChangesBeforeDiscard(MyMain main) 
{ 
    if (main.isDirty()) 
    { 
     MessageBox messageBox = new MessageBox(
      main.getShell(), 
      SWT.ICON_WARNING | SWT.YES | SWT.NO | SWT.CANCEL); 

     messageBox.setMessage("Would you like to save the changes?"); 
     messageBox.setText(MyMain.TOOL_NAME); 
     int answer = messageBox.open(); 

     if (answer == SWT.YES) 
     { 
      SaveFileAction save = new SaveFileAction(main); 
      save.run(); 

      return save.isSaved(); 
     } 
     else if (answer == SWT.NO) 
     { 
      return true; 
     } 

     return false; 
    } 

    return true; 
} 

Mise à jour 2: Btw J'utilise Sun JDK 1.6.0. Voici la sortie de la commande java -version:

java version "1.6.0_22" Java (TM) SE Runtime Environment (build 1.6.0_22-b04) Java HotSpot (TM) 64 bits serveur VM (build 17.1-b03, mode mixte)

+0

Quelle JVM utilisez-vous? –

+0

@Dave: vient d'être ajouté au texte principal – posdef

+0

Spécifiez-vous des autorisations complètes dans votre stratégie de sécurité Webstart? – qualidafial

Répondre

3

Si SaveFileAction.run() prend beaucoup de temps à s'exécuter, cela peut expliquer le gel de l'interface utilisateur.

Dans SWT, il est de votre responsabilité de faire fonctionner la pompe d'événements. En général, il ressemble à quelque chose comme:

while (!shell.isDisposed()) { 
    if (!display.readAndDispatch()) { 
    display.sleep(); 
    } 
} 

Mais parce que SWT est mono-thread, un seul événement est traité à la fois. Ainsi, si un écouteur d'événement prend beaucoup de temps à s'exécuter, l'interface utilisateur ne sera pas disponible tant que l'écouteur n'aura pas terminé et que le contrôle ne sera pas retourné à la pompe d'événements.

Lorsque des opérations de longue durée sont requises, la pratique recommandée dans SWT consiste à effectuer l'opération dans un thread de travail, en envoyant des mises à jour asynchrones à l'interface utilisateur, comme requis. sur la FAQ SWT

executor.execute(new Runnable() { 
    public void run() { 
    showStatusMessage("Saving "+filename+"..."); 

    SaveFileAction save = new SaveFileAction(main); 
    save.run(); 

    showStatusMessage("File "+filename+" saved.") 
    } 

    private void showStatusMessage(final String message) { 
    Display.getDefault().asyncExec(new Runnable() { 
     public void run() { 
     statusLine.setMessage(message); 
     } 
    }); 
    } 
}); 

This entry explique le modèle de filetage plus en détail.

+0

désolé pour une réponse très tard, je travaillais sur un manuscrit lorsque votre réponse est venue, et bien sûr les vacances ... En tout cas, je vous remercie sincèrement pour les conseils sur la gestion des processus avec SWT, mais votre théorie doesn ' J'explique vraiment pourquoi l'interface graphique se bloque même lorsque l'utilisateur échappe à toute action en utilisant le bouton Annuler. En d'autres termes, même si aucune action n'est exécutée après le déploiement de la fenêtre, l'interface graphique se bloque. Si vous avez des suggestions pour essayer et affiner le point crucial du problème, je serai heureux de fouiller dans le code :) – posdef

+0

Si votre action de sauvegarde est une opération de longue durée et que vous l'exécutez dans le thread d'affichage, alors il explique votre IU se bloquer. Pour que toute action soit gérée, y compris en cliquant sur le bouton d'annulation, le thread d'affichage doit être disponible pour traiter les événements. Tant que votre sauvegarde est en cours, le thread d'affichage n'est pas disponible. C'est pourquoi il est si important d'exécuter des opérations de longue durée sur n'importe quel thread, à l'exception du thread d'affichage. – qualidafial

+0

point intéressant, je dois creuser un peu plus et l'essayer un peu. Au fait, avez-vous une idée de la raison pour laquelle ce serait un problème spécifique à Linux, et pas sur les systèmes Windows? – posdef

1

Il y a un bogue dans SWT qui provoque ceci: here

Le bug a été résolu récemment - voir le bug pour plus d'informations.

+0

Merci pour l'info, mais il apparaît comme le bug mentionné dans le lien, et la solution fournie ici, s'applique à eclipse alors que je n'utilise pas eclipse pour la construction JWS. De plus, je n'ai pas eu de problèmes sur l'environnement Windows contrairement aux commentaires rapportés dans le buginfo. Est-ce que je manque un lien entre les problèmes? – posdef

+0

Le bug mentionne clairement la plate-forme comme GTK. De plus, alors que le titre fait référence à un plugin WebStart RCP, le même problème sous-jacent provoque un blocage de toute application SWT/Linux/Webstart. Testez la version d'intégration et voyez si elle résout votre problème. – Vik

0

J'ai juste eu un problème similaire. Je l'ai résolu en lançant le fichier jnlp avec IcedTea Java 6 Webstart (OpenJDK's javaws) au lieu de javaws d'Oracle.

Questions connexes