31 votes

Une barre de progression peut-elle être utilisée dans une classe en dehors de Main?

Pour l'instant, mon principal appelle simplement une interface graphique avec 10 lignes. Basé sur le nombre de ces lignes de texte, 1 des 9 classes (deux lignes doivent avoir le texte). La classe appelée effectue des calculs que j'aimerais avoir la barre de progression liée à l'. Voici un exemple de l'une des classes (chaque classe est similaire, mais suffisamment différentes pour justifier une nouvelle classe.) Je crois que le problème est une violation de l'EDT règles, mais tous les exemples que j'ai vu sur leur associer un argument principal. L'image s'affiche lorsque le code est exécuté, mais la barre de progression n'est pas mis à jour jusqu'à ce que tous les calculs sont terminés.

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  

30voto

trashgod Points 136305

SwingWorker est idéal pour cela. L'exemple ci-dessous effectue une itération simple en arrière-plan, tout en signalant la progression et les résultats intermédiaires dans une fenêtre. Vous pouvez passer tous les paramètres dont vous avez besoin dans un constructeur SwingWorker approprié.

 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();
            }
        });
    }
}
 

4voto

akf Points 23518

Je pense que vous prémonition est droit, vous devez adhérer à Swing filetage règles.

Alors, que faire?

Tout d'abord, je ne suis pas sûr de savoir comment votre application est conçue exactement. Vous dites que vous avez une trame principale avec un tas de lignes, et, potentiellement, chacun pourrait éventuellement appeler l'une des 9 classes, et ils se ressemblent tous comme ci-dessus. Il semble que ces classes permettent de générer leurs propres JFrame. Je suppose que ce nouveau cadre est uniquement utilisé pour la barre de progression. Je vais supposer que c'est la conception et de proposer en conséquence.

Je vous suggérons d'effectuer quelques actions dans les cas d' Runnable, et vous le déposez ceux - Runnable instances en SwingUtilities.invokeLater à les exécuter sur l'EDT. En même temps, je voudrais prendre le temps de réorganiser votre code de la facilité pour la lecture.

  1. déplacez la création de votre interface bits dans une méthode:
public void createComponents () {
 SwingUtilities.invokeLater(new Runnable() {
 public void run() {
 //Créer tous les composants
 progressFrame = new JFrame("Calcul en Cours");
 progressFrame.setSize(300, 100);
 volet = progressFrame.getContentPane();
le volet.setLayout(null);
progressFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 progressBar = new JProgressBar(0, itérations);
 //Ajouter des composants pour volet
le volet.ajouter(barre de progression);

 //Des commandes de la Position (X, Y, largeur, hauteur)
 la progressBar.setBounds(10, 10, 280, 20);

 //Faire un cadre visible
 progressFrame.setResizable(false); //Pas de redimensionnement
progressFrame.setVisible(true);
}
});

}
  1. Alors je methodize les deux actions d'interface utilisateur que vous avez dans votre calc:
 private void updateProgressBar(final int i) {
 SwingUtilities.invokeLater(new Runnable() {
 public void run() {
la progressBar.setValue(i);
 //pas besoin pour la suite
 //progressBar.repaint(); 

}
});
}

 private void killDialog() {
 SwingUtilities.invokeLater(new Runnable() {
 public void run() {
progressFrame.setVisible(false);
}
});
 } 
  1. Enfin, remplacez où le code contenu dans ces nouvelles méthodes avec des appels de méthodes.

3voto

user568422 Points 156

Merci pour l'aide. J'ai commencé par essayer d'utiliser la première réponse, mais je ne pouvais pas la barre pour s'exécuter simultanément, et il a couru lorsque le programme est terminé. Je suis sûr que ça marcherait, mais je n'étais pas en mesure de le comprendre. À l'aide de trashgod de réponse et de quelques autres exemples, j'ai été capable de le faire fonctionner à l'aide de SwingWorker. Malheureusement, je ne suis pas totalement comprendre comment il fonctionne, mais je vais le prendre pour l'instant.

L'interface graphique et la méthode à exécuter les calculs sont appelés dans une autre classe de première:

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

Puis il se déroule comme suit:

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;
}

} // fin de la classe twoLoans

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X