2011-01-09 14 views
28

En este momento, mi principal solo llama a una interfaz gráfica con 10 filas. En función de cuántas de esas filas tienen texto, se llama a 1 de 9 clases (dos filas deben tener texto). La clase llamada realiza cálculos a los que me gustaría vincular la barra de progreso. Aquí hay un ejemplo de una de las clases llamadas (cada clase es similar, pero lo suficientemente diferente como para justificar una nueva clase.) Creo que el problema es una violación de las reglas de EDT, pero todos los ejemplos que he visto en ellos implican una principal argumento. El marco aparece cuando se ejecuta el código, pero la barra de progreso no se actualiza hasta que se completan todos los cálculos.¿Se puede usar una barra de progreso en una clase externa a la principal?

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

public class twoLoan extends JFrame { 

    static JFrame progressFrame; 
    static JProgressBar progressBar; 
    static Container pane; 
    double amountSaved = 0; 
    int i = 0; 

    public void runCalcs(Double MP, Double StepAmt, 
     Double L1, Double L2, Double C1, Double C2, 
     Double IM1, Double IM2, Double M1Start, Double M2Start) { 

     try { 
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
     } catch (Exception e) { 
     } 

     int iterations = (int) (MP - (M1Start * M2Start)); 

     //Create all components 
     progressFrame = new JFrame("Calculation Progress"); 
     progressFrame.setSize(300, 100); 
     pane = progressFrame.getContentPane(); 
     pane.setLayout(null); 
     progressFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     progressBar = new JProgressBar(0, iterations); 

     //Add components to pane 
     pane.add(progressBar); 

     //Position controls (X, Y, width, height) 
     progressBar.setBounds(10, 10, 280, 20); 

     //Make frame visible 
     progressFrame.setResizable(false); //No resize 
     progressFrame.setVisible(true); 

     double M1 = M1Start; 
     double M2 = M2Start; 

     // Set MinLoop as maximum to start 
     // Loan 1 
     double N1 = (Math.log10(1 - IM1 * L1/M1) * -1)/Math.log10(1 + IM1); 
     double M1Sum = M1 * N1; 
     // Loan 2 
     double N2 = (Math.log10(1 - IM2 * L2/M2) * -1)/Math.log10(1 + IM2); 
     double M2Sum = M2 * N2; 
     double minLoop = M1Sum + M2Sum; 
     double MTotal = 0; 


     // Define variables for mins 
     double MP1 = 0; 
     double MP2 = 0; 
     double NP1 = 0; 
     double NP2 = 0; 
     double MP1Sum = 0; 
     double MP2Sum = 0; 

     while (M1 <= MP - M2Start && M2 >= M2Start) { 
      N1 = (Math.log10(1 - IM1 * L1/M1) * -1)/Math.log10(1 + IM1); 
      M1Sum = N1 * M1; 
      N2 = (Math.log10(1 - IM2 * L2/M2) * -1)/Math.log10(1 + IM2); 
      M2Sum = N2 * M2; 
      MTotal = M1Sum + M2Sum; 
      if (MTotal < minLoop) { 
       minLoop = MTotal; 
       MP1 = M1; 
       MP2 = M2; 
       NP1 = N1; 
       NP2 = N2; 
       MP1Sum = M1Sum; 
       MP2Sum = M2Sum; 
      } // end if 
      M1 = M1 + StepAmt; 
      M2 = MP - M1; 
      // Reset monthly sums 
      M1Sum = 0; 
      M2Sum = 0; 
      i++; 
      progressBar.setValue(i); 
      progressBar.repaint(); 
      if (i >= iterations) { 
       progressFrame.dispose(); 
      } 
     } // end while 

     // if there's a value for current payments, calculate amount saved 
     if (C1 > 0) { 
      double CN1 = (Math.log10(1 - IM1 * L1/C1) * -1)/Math.log10(1 + IM1); 
      double CT1 = CN1 * C1; 

      double CN2 = (Math.log10(1 - IM2 * L2/C2) * -1)/Math.log10(1 + IM2); 
      double CT2 = CN2 * C2; 

      double CTotal = CT1 + CT2; 
      amountSaved = CTotal - minLoop; 
     } 

    } // end method runCalcs 

    //Workbook wb = new HSSFWorkbook(); 
    public double savedReturn() { 
     return amountSaved; 
    } 
} // end class twoLoans 

Respuesta

28

SwingWorker es ideal para esto. El siguiente ejemplo realiza una iteración simple en segundo plano, mientras informa el progreso y los resultados intermedios en una ventana. Puede pasar los parámetros que necesite en un constructor adecuado de SwingWorker.

import java.awt.EventQueue; 
import java.awt.GridLayout; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 
import java.text.DecimalFormat; 
import java.util.List; 
import javax.swing.*; 

/** @see http://stackoverflow.com/questions/4637215 */ 
public class TwoRoot extends JFrame { 

    private static final String s = "0.000000000000000"; 
    private JProgressBar progressBar = new JProgressBar(0, 100); 
    private JLabel label = new JLabel(s, JLabel.CENTER); 

    public TwoRoot() { 
     this.setLayout(new GridLayout(0, 1)); 
     this.setTitle("√2"); 
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     this.add(progressBar); 
     this.add(label); 
     this.setSize(161, 100); 
     this.setLocationRelativeTo(null); 
     this.setVisible(true); 
    } 

    public void runCalc() { 
     progressBar.setIndeterminate(true); 
     TwoWorker task = new TwoWorker(); 
     task.addPropertyChangeListener(new PropertyChangeListener() { 

      @Override 
      public void propertyChange(PropertyChangeEvent e) { 
       if ("progress".equals(e.getPropertyName())) { 
        progressBar.setIndeterminate(false); 
        progressBar.setValue((Integer) e.getNewValue()); 
       } 
      } 
     }); 
     task.execute(); 
    } 

    private class TwoWorker extends SwingWorker<Double, Double> { 

     private static final int N = 5; 
     private final DecimalFormat df = new DecimalFormat(s); 
     double x = 1; 

     @Override 
     protected Double doInBackground() throws Exception { 
      for (int i = 1; i <= N; i++) { 
       x = x - (((x * x - 2)/(2 * x))); 
       setProgress(i * (100/N)); 
       publish(Double.valueOf(x)); 
       Thread.sleep(1000); // simulate latency 
      } 
      return Double.valueOf(x); 
     } 

     @Override 
     protected void process(List<Double> chunks) { 
      for (double d : chunks) { 
       label.setText(df.format(d)); 
      } 
     } 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       TwoRoot t = new TwoRoot(); 
       t.runCalc(); 
      } 
     }); 
    } 
} 
+0

BTW, 'main()' es solo un método que publica un 'Runnable' en la cadena de distribución del evento. Ese 'Runnable' luego construye la GUI y llama a' execute() 'en una instancia de' TwoWorker'. – trashgod

+0

¿Cómo podría ejecutar esto si en una acción realizada? ¿Sería necesario invokeLater o podría simplemente crear una instancia del SwingWorker y ejecutarlo directamente? –

+0

Esto último, como se muestra [aquí] (https://sites.google.com/site/drjohnbmatthews/randomdata). – trashgod

4

Creo que la premonición que es correcto, lo que necesita para adherirse a Swing reglas de roscado.

¿Qué hacer?

Primero, no estoy seguro de cómo está diseñada exactamente su aplicación. Usted dice que tiene un marco principal con un montón de filas, y potencialmente cada uno podría potencialmente llamar a una de las 9 clases, y todas se ven como la de arriba. Parece que estas clases generarán su propio JFrame. Supongo que este nuevo fotograma se usa únicamente para la barra de progreso. Asumiré que este es el diseño y sugeriré en consecuencia.

que sugieren que realice un par de acciones en casos de Runnable, y te deja esos casos en RunnableSwingUtilities.invokeLater para que se ejecuten en la EDT. Al mismo tiempo, me tomaría el tiempo para reorganizar su código para facilitar la lectura.

  1. medida la creación de sus bits de interfaz gráfica de usuario en un método:
public void createComponents() { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      //Create all components 
      progressFrame = new JFrame("Calculation Progress"); 
      progressFrame.setSize(300, 100); 
      pane = progressFrame.getContentPane(); 
      pane.setLayout(null); 
      progressFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      progressBar = new JProgressBar(0, iterations); 
      //Add components to pane 
      pane.add(progressBar); 

      //Position controls (X, Y, width, height) 
      progressBar.setBounds(10, 10, 280, 20); 

      //Make frame visible 
      progressFrame.setResizable(false); //No resize 
      progressFrame.setVisible(true); 
     } 
     }); 

    } 
  1. entonces yo metodizar las dos acciones interfaz gráfica de usuario que tiene almacenado en su Calc:
 
    private void updateProgressBar(final int i) { 
      SwingUtilities.invokeLater(new Runnable() { 
       public void run() { 
        progressBar.setValue(i); 
        //no need for the following 
        //progressBar.repaint(); 

       } 
      }); 
    } 

    private void killDialog() { 
      SwingUtilities.invokeLater(new Runnable() { 
       public void run() { 
        progressFrame.setVisible(false); 
       } 
      }); 
    } 
  1. Por último, reemplace donde la c oda contenida en estos nuevos métodos con llamadas a los métodos.
+0

muchas gracias por su ayuda, he estado atrapado en este por un tiempo.He estado trabajando en ello, pero no puedo encontrar la manera de llamar a los nuevos métodos en tiempo real. Con mi código actualizado, se crea la GUI y la barra de progreso se actualiza después de realizar los cálculos. ¿Te importaría ayudarme con llamar a los métodos? Todo lo que he llamado "de manera similar dentro runCalcs" de la siguiente manera: SwingUtilities.invokeLater (nueva Ejecutable() { public void run() { createComponents (iteraciones); } }); – user568422

3

Gracias por la ayuda. Empecé tratando de usar la primera respuesta, pero no pude hacer que la barra se ejecutara simultáneamente, y se ejecutó cuando el programa finalizó. Estoy seguro de que funcionaría, pero no fui capaz de resolverlo. Usando la respuesta de trashgod y algunos otros ejemplos, pude hacer que funcione usando SwingWorker. Desafortunadamente, no entiendo totalmente cómo funciona, pero lo tomaré por ahora.

la GUI y el método para ejecutar los cálculos son llamados en otra clase primera:

iterations = (int) (MPay - (M1Start + M2Start)); 
     twoLoan myLoan = new twoLoan(); 
     myLoan.createGui(iterations); 
     myLoan.runCalcs(MPay, Step, L1, L2, C1, C2, IM1, IM2, M1Start, M2Start); 

Entonces es como sigue:

public class twoLoan extends JFrame { 

    JFrame progressFrame; 
    JProgressBar progressBar; 
    JLabel label = new JLabel("Calculating...");; 
    Container pane; 

    double amountSaved = 0; 
    int i = 0; 
    int iterations; 

    public void createGui(int iterations) { 
      //Create all components 
      progressFrame = new JFrame("Calculation Progress"); 
      progressFrame.setSize(300, 100); 
      pane = progressFrame.getContentPane(); 
      pane.setLayout(null); 
      label = new JLabel("Calculating..."); 
      label.setBounds(115, 35, 200, 25); 
      progressBar = new JProgressBar(0, iterations); 
      progressBar.setBounds(10, 10, 280, 20); 
      progressBar.setStringPainted(true); 
      //Add components to pane 
      pane.add(progressBar); 
      pane.add(label); 
      //Make frame visible 
      progressFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      progressFrame.setResizable(false); //No resize 
      progressFrame.setLocationRelativeTo(null); 
      progressFrame.setVisible(true); 
    } 

    public void runCalcs (double MP, double StepAmt, double L1, double L2, 
      double C1, double C2, double IM1, double IM2, double M1Start, double M2Start) { 

     progressBar.setIndeterminate(false); 
     TwoWorker task = new TwoWorker(MP, StepAmt, L1, L2, C1, C2, IM1, IM2, M1Start, M2Start); 
     task.addPropertyChangeListener(new PropertyChangeListener() { 

      @Override 
      public void propertyChange(PropertyChangeEvent e) { 
       if ("progress".equals(e.getPropertyName())) { 
        progressBar.setIndeterminate(false); 
        progressBar.setValue((Integer) e.getNewValue()); 
       } 
      } 
     }); 
     task.execute(); 
    } //end method runCalcs 

    public class TwoWorker extends SwingWorker<Double, Double> { 

     private final double MP, StepAmt,L1, L2, 
      C1, C2, IM1, IM2, M1Start, M2Start; 

     public TwoWorker(double MPa, double StepAmta, double L1a, double L2a, 
      double C1a, double C2a, double IM1a, double IM2a, double M1Starta, double M2Starta) { 

      MP = MPa; 
      StepAmt = StepAmta; 
      L1 = L1a; 
      L2 = L2a; 
      C1 = C1a; 
      C2 = C2a; 
      IM1 = IM1a; 
      IM2 = IM2a; 
      M1Start = M1Starta; 
      M2Start = M2Starta; 
      } 
     @Override 
     protected Double doInBackground() { 

      double M1 = M1Start; 
      double M2 = M2Start; 

     // Set MinLoop as maximum to start 
     // Loan 1 
     double N1 = (Math.log10(1 - IM1 * L1/M1) * -1)/Math.log10(1 + IM1); 
    double M1Sum = M1 * N1; 
    // Loan 2 
    double N2 = (Math.log10(1 - IM2 * L2/M2) * -1)/Math.log10(1 + IM2); 
    double M2Sum = M2 * N2; 
    double minLoop = M1Sum + M2Sum; 
    double MTotal = 0; 

     // Define variables for mins 
    double MP1 = 0; 
    double MP2 = 0; 
    double NP1 = 0; 
    double NP2 = 0; 
    double MP1Sum = 0; 
    double MP2Sum = 0; 

     while (M1 <= MP - M2Start && M2 >= M2Start) { 
      N1 = (Math.log10(1 - IM1 * L1/M1) * -1)/Math.log10(1 + IM1); 
      M1Sum = N1 * M1; 
      N2 = (Math.log10(1 - IM2 * L2/M2) * -1)/Math.log10(1 + IM2); 
      M2Sum = N2 * M2; 
      MTotal = M1Sum + M2Sum; 
      if (MTotal < minLoop) { 
       minLoop = MTotal; 
       MP1 = M1; 
       MP2 = M2; 
       NP1 = N1; 
       NP2 = N2; 
       MP1Sum = M1Sum; 
       MP2Sum = M2Sum; 
      } // end if 
         i++; 
         progressBar.setValue(i); 
        M1 = M1 + StepAmt; 
      M2 = MP - M1; 
      // Reset monthly sums 
      M1Sum = 0; 
      M2Sum = 0; 
     } // end while 

     System.out.printf("MP1 = %.2f\n", MP1); 
     System.out.printf("MP2 = %.2f\n", MP2); 
     System.out.printf("NP1 = %.2f\n", NP1); 
     System.out.printf("NP2 = %.2f\n", NP2); 
     System.out.printf("MP1Sum = %.2f\n", MP1Sum); 
     System.out.printf("MP2Sum = %.2f\n", MP2Sum); 
       System.out.printf("MTotal = %.2f\n", minLoop); 
       System.out.printf("i = %d\n",i); 
       System.out.printf("M1Start = %.2f\n", M1Start); 
     System.out.printf("M2Start = %.2f\n", M2Start); 
       System.out.printf("MP= %.2f\n",MP); 

    // if there's a value for current payments, calculate amount saved 
    if(C1 > 0) { 
     double CN1 = (Math.log10(1 - IM1 * L1/C1) * -1)/Math.log10(1 + IM1); 
     double CT1 = CN1 * C1; 

     double CN2 = (Math.log10(1 - IM2 * L2/C2) * -1)/Math.log10(1 + IM2); 
     double CT2 = CN2 * C2; 

     double CTotal = CT1 + CT2; 
     amountSaved = CTotal - minLoop; 
     } // end if 

     return null; 

    } // end doInBackGround 

     @Override 
     protected void done() { 
      label.setBounds(133, 35, 200, 25); 
      label.setText("Done!"); 
     } 
    } // end TwoWorker 


    public double savedReturn() { 
     return amountSaved; 
    } 

} // end class twoLoans 
Cuestiones relacionadas