Programar no es fácil y agregar una interfaz de usuario en torno a la funcionalidad realmente puede complicar la vida. Especialmente porque no todos los marcos de interfaz de usuario son seguros para subprocesos (incluido Swing). Entonces, ¿cómo manejamos de manera eficiente la interfaz de usuario, ejecutamos el código de trabajador y comunicamos datos entre los dos, todo mientras mantenemos la interfaz de usuario receptiva?
Te puede interesar:Ejemplo: carga de una clase Java en tiempo de ejecuciónAfortunadamente para los usuarios de Swing, hay algunas opciones, las cuales pueden hacer que las GUI de programación sean mucho más simples. Aquí tienes dos de esas opciones.
Te puede interesar:Pruebas unitarias en Java con JUnit 5Invocar más tarde
SwingUtilities.invokeLater()
es ideal para actualizar la interfaz de usuario desde otro hilo. Tal vez tenga una tarea de larga duración y le gustaría actualizar una barra de progreso para proporcionar comentarios al usuario. Podrías probar algo como esto:
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
progressBar.setValue(0);
progressBar.setStringPainted(true);
// Runs outside of the Swing UI thread
new Thread(new Runnable() {
public void run() {
for (i = 0; i <= 100; i++) {
// Runs inside of the Swing UI thread
SwingUtilities.invokeLater(new Runnable() {
public void run() {
progressBar.setValue(i);
}
});
try {
java.lang.Thread.sleep(100);
}
catch(Exception e) { }
}
}
}).start();
}
});
Con suerte, puede ver en este ejemplo cómo podría usar SwingUtilities.invokeLater()
para comunicarse entre la interfaz de usuario y los subprocesos de trabajo. Tu puedes pensar en invokeLater
como una simple devolución de llamada a la interfaz de usuario para enviar las actualizaciones que necesite.
Trabajador de swing
SwingWorker<T,V>
se puede utilizar de forma similar a invokeLater
, pero cada uno tiene sus puntos fuertes. Personalmente, prefiero usar SwingWorker
para tareas de larga duración para las que no necesito actualizar la interfaz de usuario (como cargar un documento grande), mientras invokeLater
podría usarse más para tareas de larga duración que necesitan actualizar la interfaz de usuario. SwingWorker
se puede utilizar de esta forma con:
private Document doc;
JButton button = new JButton("Open XML");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// All code inside SwingWorker runs on a seperate thread
SwingWorker<Document, Void> worker = new SwingWorker<Document, Void>() {
@Override
public Document doInBackground() {
Document intDoc = loadXML();
return intDoc;
}
@Override
public void done() {
try {
doc = get();
} catch (InterruptedException ex) {
ex.printStackTrace();
} catch (ExecutionException ex) {
ex.printStackTrace();
}
}
};
// Call the SwingWorker from within the Swing thread
worker.execute();
}
});
Esta clase divide los eventos de los trabajadores en métodos que se pueden implementar según sus necesidades. Para un uso más avanzado, consulte el publish(V... chunks)
y process(List<V> chunks)
métodos.
Recursos
- http://en.wikipedia.org/wiki/SwingWorker
- http://en.wikipedia.org/wiki/Continuation-passing_style#Continuations_as_objects
Te puede interesar:Modificadores de acceso en Java