Foro sobre Java SE > Ayuda para el uso de hilos, threads para aplicar a JProgressBar
Lo que necesitas es que las tareas que lleve tiempo ejecutar las implementes extendiendo la clase SwingWorker:
http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
http://www.oracle.com/technetwork/articles/javase/index-141911.html
La idea es:
- Creas una clase que extiende SwingWorker<T, V>, donde "T" es la clase que devolverás como resultado final y "V" la clase de los resultados intermedios. Por ejemplo, en tu caso podrías querer devolver como resultado final una clase que contenga una serie de datos sobre la configuración realizada (referencia al socket, dirección IP, mensajes de error...) y como resultados intermedios objetos String con mensajes de progreso.
- En esa clase que creas sólo es estrictamente necesario que implementes el método doInBackground(). En este método harías más o menos lo que ahora haces en configurarDatos(). Sin embargo, normalmente necesitarás implementar también el método done() y, si publicas resultados intermedios, el método publish(). Ten en cuenta que los resultados intermedios son independientes de la barra de progreso; si sólo quieres hacer avanzar la barra de progreso, no necesitas resultados intermedios.
- Para poder mostrar la barra de progreso necesitas escribir una clase que implemente PropertyChangeListener. En su constructor suministras una referencia al JProgressBar que quieres actualizar y, si lo quieres hacer más genérico, al nombre de la propiedad que debe observar (que, para un SwingWorker, es "progress"). Su método propertyChange es algo así:
@Override
public void propertyChange(PropertyChangeEvent evt) {
String eventProperty = evt.getPropertyName();
if (this.observedProperty.equals(eventProperty)) {
int newValue = (Integer) evt.getNewValue();
this.progressBar.setProgress(newValue);
}
}
- En el método doInBackground vas actualizando la propiedad progress de la propia clase SwingWorker cada vez que estés avanzando. Por ejemplo:
protected <T> doInBackground() throws Exception {
// Haces algo que supone el 10 % de la tarea
...
// Y actualizas progress
this.setProgress(10);
// "Asín" sucesivamente
...
// Y ya has acabado; te aseguras de que el progreso indique que has terminado
this.setProgress(100);
}
- antes de lanzar la ejecución del SwingWorker, registras el listener sobre él:
SocketConfiguratorWorker<SocketConfigResult, String> scw = new SocketConfiguratorWorker<>(<datos que necesites para el constructor>);
ProgressBarListener pbl = new ProgressBarListener(jProgressBar1, "progress");
scw.addPropertyChangeListener(pbl);
Cordial saludo, tengo un pequeño problema con la implementación de hilos, resulta que tengo una aplicación que funciona bien, me configura un equipo al presionar un botón, la clase que tengo es la siguiente:
public CSCM(javax.swing.JDialog parent, boolean modal) {
super(parent, modal);
initComponents();
setTitle("Configuración de módem");
}
@SuppressWarnings("unchecked")
private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {
try
{
// Open a client socket connection
Socket clientSocket = new Socket("192.168.0.1", 23);
System.out.println("Client1: " + clientSocket);
// User defined Method
configurarDatos(clientSocket);
}
catch (UnknownHostException uhe)
{
System.out.println("UnknownHostException: " + uhe);
}
catch (IOException ioe)
{
System.err.println("IOException: " + ioe);
}
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
CSAVN AbrirCSAVN = new CSAVN(new javax.swing.JDialog(), true);
dispose();
AbrirCSAVN.setVisible(true);
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
CSMG AbrirCSMG = new CSMG(new javax.swing.JDialog(), true);
dispose();
AbrirCSMG.setVisible(true);
}
private static void configurarDatos(Socket clientSocket)
{
try
{
// Acquire the input and output streams
String[] leeDatos = new LeeDatos().getDatos();
DataOutputStream outbound = new DataOutputStream(
clientSocket.getOutputStream() );
BufferedReader inbound = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()) );
//outbound.writeBytes("Administrator");
//outbound.writeBytes("\n");
outbound.writeBytes("14125665");
outbound.writeBytes("\r");
System.out.println("Ingresando clave");
try { Thread.sleep ( 2000) ; } catch ( InterruptedException ie) { }
outbound.writeBytes("set wan node proveedor");
outbound.writeBytes("\r");
try { Thread.sleep ( 2000) ; } catch ( InterruptedException ie) { }
outbound.writeBytes("set wan node proveedor");
outbound.writeBytes("\r");
System.out.println("Iniciando configuración datos");
try { Thread.sleep ( 1000) ; } catch ( InterruptedException ie) { }
outbound.writeBytes("set wan ppp username "+leeDatos[2]);
outbound.writeBytes("\r");
System.out.println("Configurando nombre de usuario");
try { Thread.sleep ( 1000) ; } catch ( InterruptedException ie) { }
outbound.writeBytes("set wan ppp password "+leeDatos[3]);
outbound.writeBytes("\r");
System.out.println("Configurando contraseña");
try { Thread.sleep ( 2000) ; } catch ( InterruptedException ie) { }
outbound.writeBytes("set wan save");
outbound.writeBytes("\r");
System.out.println("Guardando datos");
try { Thread.sleep (2000) ; } catch ( InterruptedException ie) { }
outbound.writeBytes("set wan save");
outbound.writeBytes("\r");
System.out.println("Guardando datos 2");
outbound.close();
inbound.close();
clientSocket.close();
}
catch (IOException ioe)
{
System.out.println("IOException: " + ioe);
}
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
CSCM dialog = new CSCM(new javax.swing.JDialog(), true);
dialog.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent e) {
System.exit(0);
}
});
dialog.setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JButton jButton4;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
// End of variables declaration
}
Cuando se están ejecutando las órdenes, el proceso se demora 12 segundos, así que hice una prueba en otra ventana para mostrar una barra de progreso, también me funciona bien.
public class Prueba extends javax.swing.JDialog {
public Prueba(javax.swing.JDialog parent, boolean modal) {
super(parent, modal);
initComponents();
setIconImage(new ImageIcon(getClass().getResource("/imagenes/poporo.png")).getImage());
}
public class progreso implements ActionListener{
public void actionPerformed(ActionEvent evt){
int n = jProgressBar1.getValue();
if(n<100){
n++;
jProgressBar1.setValue(n);
jProgressBar1.setStringPainted(rootPaneCheckingEnabled);
jProgressBar1.setString("Configurando módem...");
}else{
timer.stop();
JOptionPane.showMessageDialog(null, "Configuración terminada");
jProgressBar1.setStringPainted(false);
}
}
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jLabel1 = new javax.swing.JLabel();
jProgressBar1 = new javax.swing.JProgressBar();
Prueba = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowOpened(java.awt.event.WindowEvent evt) {
formWindowOpened(evt);
}
});
jLabel1.setText("La pruebita");
jProgressBar1.setString("\"Configurando módem...\"");
Prueba.setText("jButton1");
Prueba.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
PruebaActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(165, 165, 165)
.addComponent(jLabel1))
.addGroup(layout.createSequentialGroup()
.addGap(131, 131, 131)
.addComponent(Prueba)))
.addContainerGap(181, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 355, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(21, 21, 21))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(74, 74, 74)
.addComponent(jLabel1)
.addGap(88, 88, 88)
.addComponent(Prueba)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 32, Short.MAX_VALUE)
.addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(37, 37, 37))
);
pack();
}// </editor-fold>
private void PruebaActionPerformed(java.awt.event.ActionEvent evt) {
timer.start();
}
private void formWindowOpened(java.awt.event.WindowEvent evt) {
timer = new Timer(50, new progreso());
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
Prueba dialog = new Prueba(new javax.swing.JDialog(), true);
dialog.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent e) {
System.exit(0);
}
});
dialog.setVisible(true);
}
});
}
private Timer timer;
// Variables declaration - do not modify
private javax.swing.JButton Prueba;
private javax.swing.JLabel jLabel1;
private javax.swing.JProgressBar jProgressBar1;
// End of variables declaration
}
No se como hago para integrar estas dos clases para que al presionar el botón de la primera clase me haga los dos procesos simultáneamente, tengo entendido que cada una se debe ejecutar en un hilo, pero no he podido, agradezco cualquier colaboración e indicaciones.