Forcer un JFrame pour rafraîchir
Question
J'ai une interface utilisateur construit à l'intérieur d'un JFrame. L'un des boutons commence un long appel en cours d'exécution (toujours dans le même processus java), et pendant son exécution, l'interface utilisateur est gelé.
Je me suis dit, de faire comprendre que les choses sont encore en cours d'exécution, je peux afficher une barre de progression, peut-être dans une fenêtre contextuelle, de sorte que l'utilisateur peut être tenue à jour à ce que le programme est en train de faire.
Alors je crée une nouvelle JDialog, en ajoutant un JProgressBar à lui, et le mettre à jour que les choses se passent. Le problème est que le contenu de cette boîte de dialogue ne se mis à jour. Les changements que je fais à son titre montrer immédiatement, et tout ce que je sortie à la console, mais rien dans l'interface utilisateur lui-même.
Y at-il une commande que je peux émettre pour forcer un repeindre?
Voici le coeur de cette section:
killWindow = new JDialog();
killWindow.setUndecorated(true);
killWindow.setTitle("stopping tests - 0 of " + numActive);
killProgress = new JProgressBar(0, numActive);
killWindow.add(killProgress);
killProgress.setStringPainted(true);
killWindow.pack();
killWindow.setLocationRelativeTo(frame);
killWindow.setVisible(true);
Alors, comme nous progressons ...:
killProgress.setValue(++killedTests); // not seen!
killProgress.setString("Killing test on " + nickname()); // not seen!
log("Killed another test, " + killedTests + " so far"); // visible in real time
killWindow.setTitle("stopping tests - " + killedTests +
" of " + killProgress.getMaximum()); // visible in real time
Qu'est-ce que je manque? J'ai essayé googler et de la recherche ici sur le SO, et ne l'ont pas vraiment vu quelque chose évidente?
La solution
Vous devez effectuer votre longue tâche en cours d'exécution dans un autre thread.
Il y a ce fil appelé « AWT Dispatch événement discussion » qui est responsable de la mise à jour des composants de l'interface utilisateur. Si elle est en train d'effectuer votre tâche longue en cours, il pas mettre à jour l'interface utilisateur (ni vous rafraîchir dialogue).
Vous pouvez envisager d'utiliser SwingUtilities ou un SwingWorker .
De la documentation noreferrer"> du SwingWorker ici est un échantillon
final JLabel label;
class MeaningOfLifeFinder extends SwingWorker<String, Object> {
@Override
public String doInBackground() {
return findTheMeaningOfLife();
}
@Override
protected void done() {
try {
label.setText(get());
} catch (Exception ignore) {
}
}
}
(new MeaningOfLifeFinder()).execute();
En exécutant votre tâche longue dans un autre thread, vous autorisez le fil événement AWT d'expédition pour montrer une interface utilisateur réactive.
Vous pouvez jeter un oeil à ce « Leçon de la Java tutoriel » pour mieux comprendre ces concepts.
Autres conseils
On dirait que vous pourriez exécuter votre tâche longue en cours d'exécution sur le fil Dispatch Event (HAE). Jetez un oeil à SwingWorker. Si vous utilisez 1.6, il est construit en:
http://java.sun.com /javase/6/docs/api/javax/swing/SwingWorker.html
Dans le cas contraire, vous pouvez trouver plus d'infos sur: