ProgressBar updaten

Carcharoth

Bekanntes Mitglied
Hallo

In meinem Miniprojekt versuche ich den Fortschritt einer Berechnung in einer ProgressBar auf einer GUI (Klasse UF) abzubilden.
In der Klasse UF habe ich dazu eine Methode udpateProgressBar gebaut.

Damit in der Klasse Berechnung die progressBar updaten kann, musste ich die Methode updateProgressBar als public static definieren (somit musste ich auch die ProgressBar als static deklarieren).

Funktioniert auch alles.
Meine Frage: ist das der richtige Weg ?

Dann noch Zusatzfrage: ich tue mich immer noch etwas schwer mit dem Threading vs. Swing. Scheint euch das hier so sinnvoll umgesetzt

Danke und Gruss

Java:
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;

public class UF extends JFrame {

    private JPanel contentPane;
    private static JProgressBar progressBar;
    private JButton btnNewButton;
    
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    UF frame = new UF();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public static void udpateProgressBar(int value) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                progressBar.setValue(value);
            }
        });
    }
        
    public UF() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);
        
        progressBar = new JProgressBar();
        progressBar.setBounds(28, 142, 358, 14);
        progressBar.setValue(0);
        progressBar.setStringPainted(true);
        contentPane.add(progressBar);
        
        btnNewButton = new JButton("New button");
        btnNewButton.setBounds(28, 28, 89, 23);
        btnNewButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                new Thread(new Runnable() {
                    public void run() {
                        Berechnung berechnung = new Berechnung();
                    }
                }).start();
            }
        });
        contentPane.add(btnNewButton);
        
        setVisible(true);
    }
}
 
Also bis auf das static sieht alles gut aus. Du machst es nicht static, weder die Methode noch die ProgressBar.

Statt dessen gibst du der Berechnung eine entsprechende Referenz mit, auf der du das aufrufen kannst.

Eine Möglichkeit wäre, da Consumer<Integer> als Parameter mit zu übergeben - kann kannst du eine Methodenreferenz übergeben zu der Methode, die die Aktualisierung macht. Und statt dem aktualisieren rufst du halt auf dem übergebenen Consumer das accept auf.
 
Ich habe mich etwas eingelesen aber muss zugeben, dass ich noch nicht so ganz durchblicke was es mit dem Consumer auf sich hat.
Ich habe es so umgesetzt. Funktioniert. Ist es deiner Meinung nach korrekt ?

Java:
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.function.IntConsumer;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;

public class UF extends JFrame {

    private JPanel contentPane;
    private static JProgressBar progressBar;
    private JButton btnNewButton;
    
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    UF frame = new UF();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public static void udpateProgressBar(int value) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                progressBar.setValue(value);
            }
        });
    }
        
    public UF() {
        IntConsumer consumer = i -> udpateProgressBar(i);
        
        ...
        
        btnNewButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                new Thread(new Runnable() {
                    public void run() {
                        Berechnung berechnung = new Berechnung(consumer);
                    }
                }).start();
            }
        });
        
        ...
        
    }
}


und


Java:
public class Berechnung {

    Berechnung(IntConsumer consumer) {
        double startingNumber = 0;
        while (startingNumber<=10000000) {
            consumer.accept((int)startingNumber/100000);

            ...
 
Ja, das sieht gut aus. Genau so war es gemeint.

Die lokale Variable consumer spart man sich in der Regel und schreibt direkt entweder mit Lambda:
Java:
Berechnung berechnung = new Berechnung(i -> updateProgress(i));

oder etwas kürzer mit Methodenreferenz:
Java:
Berechnung berechnung = new Berechnung(this::updateProgress);

Aber es spricht nichts dagegen, das erst in eine lokale Variable zu stecken wie Du es gemacht hast.

Das auch nur als kleine Anmerkung: Du kannst die anonymen Klassen auch so ersetzen (So es ein funktionales Interface ist, also nur eine Methode zu schreiben ist):

Aus:
Java:
                new Thread(new Runnable() {
                    public void run() {
                        Berechnung berechnung = new Berechnung(consumer);
                    }
                }).start();

könntest Du etwas kürzer machen:
Java:
                new Thread( () -> new Berechnung(this::updateProgress) ).start();

Aber wie schon gesagt: Nur eine kleine Anmerkung - Es spricht nichts dagegen, den Code so zu lassen, so Du Dich mit diesen Lambda Ausdrücken und Methoden Referenzen noch nicht so wohl fühlen solltest.
 
Danke für die Tipps. Die werde ich mir nach und nach aneignen. Muss immer darauf achten, dass die Neuigkeiten verdaulich bleiben ;-)

Gruss und danke für die Unterstützung.
 

Zurück
Oben