JProgressbar ändert werte nicht

  • Themenstarter Themenstarter Tomate_Salat
  • Beginndatum Beginndatum
Status
Nicht offen für weitere Antworten.
T

Tomate_Salat

Gast
Hi,

also, mein Quelltext ist wohl zu groß und zu komplex um ihn hier zu posten, der würde wohl mehr verwirren. Aber ich denke ich kann es gut erklären:

ich habe eine JAR-Datei, in der alle funktionalitäten stehen und in der ist eine Funktion, deren Teilaufgabe es ist, die JProgressbar aktuell zu halten.

So diese Datei wird in mein Projekt eingebunden.

Als erstes hatte ich die Anzeige getestet. Die Funktion verschiebt Dateien von A nach B. Also hab ich mal 2000 Dateien verschoben und bei 1000 mir eine Ausgabe über JOptionPane geben lassen. Das führte zu einer Pausierung des Programms und ich konnte 50% ablesen. Soweit so gut. Jz wollte ich den wachstum verfolgen und habe eine:
Thread.sleep(10) eingebaut. Die funktioniert auch, denn der letzte durchlauf dauerte länger mit den gleichen Dateien.

NUR: Ich bekomme absolut keinen Wachstum angezeigt: Es steht nur 0% und beim ende 100%

Wie kann ich die JProgressbar dazu bringen, mir korrekte werte anzeigen zu lassen?

MFG

tomate_salat
 
Du führst deine Funktion im Event Dispatch-Thread aus. Das ist verkehrt. Benutze einen eigenen Thread.
Mit dem Swingworker ist das am einfachsten.
 
ein eigener Thread wäre hier aber total unnötig, ich will nur testen, ob die Progressbar sich aktuallisiert.
Bei größeren Dateimengen (mit denen ich demnächst arbeiten muss) wichtig, dass ich da eine rückmeldung bekomme.

gebe es sonst noch eine Möglichkeit, das Programm ohne Threads zu "pausieren"?
 
Hallo,
ein eigener Thread wäre hier aber total unnötig, ich will nur testen, ob die Progressbar sich aktuallisiert....
Leider ist hier doch ein eigener Thread notwendig. Deine PB kommt nämlich nicht zum Zuge, da erstmal deine Verarbeitung loslegt. Ne einfache Lösung könnte das ändern des Cursor in einen Wait Cursor vorher und nachher wieder in einen normalen Cursor sein. Allerdings ist das keine wirklich Schöne Lösung, außerdem verstärken solche Krücken den Eindruck Swing wäre langsam und träge...
Ciao velaluka
 
geht das nicht, dass ich der Methode die Progressbar übergebe und der nach jeder verschiebung einfach die Methode
setValue()
aufruft und den Wert editiert?!
 
Nein. Die Anzeige des Progressbar wird nicht aktualisiert, da deine Aktion den EDT blockiert.
Verwende einen Swingworker, siehe Link. Das ist ganz einfach.
 
Hallo,
geht das nicht, dass ich der Methode die Progressbar übergebe und der nach jeder verschiebung einfach die Methode
setValue()
aufruft und den Wert editiert?
Nein, die Frage ist auch nicht, ob deine PB den aktuellen Value kennt, sondern wann sie neu gezeichent wird...
Ciao velaluka
 
äh wie soll den der Swingworker mit Rekursiven Methoden arbeiten?!
 
ich habs versucht und aber mit dem SwingWorker geht der iwie nicht in die Rekursion rein....der hat mir nur einen Ordner verschoben

Nochmal was die Funktionen machen:

ich habe eine Funktion, die geht Rekursiv durch einen Ordner-bereich durch und verschiebt alles, zu einem bestimmten ziel. Sie zählt ebenso jede verschobene Datei mit.

Jetzt will ich mit jeder verschobenen Datei die Progressbar updaten, so dass sie mir einen Vortschritt anzeigt.
 
Zuletzt bearbeitet von einem Moderator:
Juhu Tomate,
sieh dir hier mal die letzten 3 Folien an, das sollte dein Problem beschreiben und lösen...:rtfm:
Ciao velaluka
 
aber die done()-Methode wird doch erst aufgerufen, wenn (in meinem Falle) ALLES verschoben wurde. D.h. das einzigste was ich übergeben kann ist dann: Zeig 100% an.
 
Ja, aber die publish()-Methode kannst du zwischendurch aufrufen. In der process()-Methode wird dann dass aus der publish()-Methode veröffentlichte Ergebnis weiter verarbeitet.
Der Clou ist, dass der SwingWorker ausserhalb des EventDispathTread arbeitet, die GUI Neuzeichung also nicht verhindert, die process()-Methode jedoch sehr wohl im EDT arbeitet, hier also die GUI aktualisiert werden kann.

also quasi:

Java:
...
protected Integer doInBackground()
{
 for(int counter=0; counter<100; counter++)
 {
  publish(counter);
 }
 return counter;
}

protected void process(List<Integer> chunks)
{
   progressbar.setValue(chunks.get(0));
}
...
 
Hallo,
Der Clou ist, dass der SwingWorker ausserhalb des EventDispathTread arbeitet, die GUI Neuzeichung also nicht verhindert, die process()-Methode jedoch sehr wohl im EDT arbeitet, hier also die GUI aktualisiert werden kann.
oder halt die setProgress Methode verwenden und in der GUI als PropertyChange Listener die PB aktualisieren...
Java:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */ 

package components;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.beans.*;
import java.util.Random;

public class ProgressBarDemo extends JPanel
                             implements ActionListener, 
                                        PropertyChangeListener {

    private JProgressBar progressBar;
    private JButton startButton;
    private JTextArea taskOutput;
    private Task task;

    class Task extends SwingWorker<Void, Void> {
        /*
         * Main task. Executed in background thread.
         */
        @Override
        public Void doInBackground() {
            Random random = new Random();
            int progress = 0;
            //Initialize progress property.
            setProgress(0);
            while (progress < 100) {
                //Sleep for up to one second.
                try {
                    Thread.sleep(random.nextInt(1000));
                } catch (InterruptedException ignore) {}
                //Make random progress.
                progress += random.nextInt(10);
                setProgress(Math.min(progress, 100));
            }
            return null;
        }

        /*
         * Executed in event dispatching thread
         */
        @Override
        public void done() {
            Toolkit.getDefaultToolkit().beep();
            startButton.setEnabled(true);
            setCursor(null); //turn off the wait cursor
            taskOutput.append("Done!\n");
        }
    }

    public ProgressBarDemo() {
        super(new BorderLayout());

        //Create the demo's UI.
        startButton = new JButton("Start");
        startButton.setActionCommand("start");
        startButton.addActionListener(this);

        progressBar = new JProgressBar(0, 100);
        progressBar.setValue(0);
        progressBar.setStringPainted(true);

        taskOutput = new JTextArea(5, 20);
        taskOutput.setMargin(new Insets(5,5,5,5));
        taskOutput.setEditable(false);

        JPanel panel = new JPanel();
        panel.add(startButton);
        panel.add(progressBar);

        add(panel, BorderLayout.PAGE_START);
        add(new JScrollPane(taskOutput), BorderLayout.CENTER);
        setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));

    }

    /**
     * Invoked when the user presses the start button.
     */
    public void actionPerformed(ActionEvent evt) {
        startButton.setEnabled(false);
        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        //Instances of javax.swing.SwingWorker are not reusuable, so
        //we create new instances as needed.
        task = new Task();
        task.addPropertyChangeListener(this);
        task.execute();
    }

    /**
     * Invoked when task's progress property changes.
     */
    public void propertyChange(PropertyChangeEvent evt) {
        if ("progress" == evt.getPropertyName()) {
            int progress = (Integer) evt.getNewValue();
            progressBar.setValue(progress);
            taskOutput.append(String.format(
                    "Completed %d%% of task.\n", task.getProgress()));
        } 
    }


    /**
     * Create the GUI and show it. As with all GUI code, this must run
     * on the event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("ProgressBarDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        JComponent newContentPane = new ProgressBarDemo();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
Ciao velaluka
 
Sagt mal,
ich poste gerade das BSP von Sun und sehe dann das hier
Java:
 /**
     * Invoked when task's progress property changes.
     */
    public void propertyChange(PropertyChangeEvent evt) {
        if ("progress" == evt.getPropertyName()) {
            int progress = (Integer) evt.getNewValue();
            progressBar.setValue(progress);
            taskOutput.append(String.format(
                    "Completed %d%% of task.\n", task.getProgress()));
        } 
    }
"==" kann doch, aber muss doch nicht immer funktionieren, oder???
Ciao velaluka
 
WTF, testlauf gemacht, das publish ist am ANFANG meiner methode und ich hab ihm ein
Java:
System.out.println("liste" + map.size());
verpasst......das wird bei mir ZUM SCHLUSS!!! aufgerufen!
 
hmm werde wohl die funktin iwie umschreiben müssen, dass die mit 2 threads läuft.
Der SwingWorker funktioniert bei mir nicht mal ansatzweise, wie er sollte
 
bringt nichts, mir geht es darum:
die process-anweisung wird erst zum schluss ausgeführt, die müsste aber ständig, während des Prozesses ausgeführt werden!
 
Java:
public static int ANZAHL = 0;

[java=115]
public int moveNTo(final File from, final File to, final int filter, final String[] details, final JProgressBar bar) throws DateienException {
final HashMap<Integer, String> map = new HashMap<Integer, String>();

ANZAHL = 0;

Thread moving = new Thread() {
@Override
public void run() {
try {
moveNToRK(from, to, map, filter, details, null);
interrupt();
} catch (DateienException e) {
e.printStackTrace();
}
}
};

Thread pBar = new Thread() {
public void run() {
while(true)
bar.setValue(ANZAHL);
};
};

moving.start();
pBar.start();

while(moving.isAlive());

pBar.interrupt();

Date date = new Date();
String space= "_";
String name = "move_" + (date.getYear() + 1900) + space + date.getMonth() + space + date.getDate() + space + date.getHours() + space + date.getMinutes() + space + date.getSeconds() + ".rep";
String path = "report\\";
File fPath = new File(path);

// Legt den Report-Ordner an, falls er nicht existiert
if(!fPath.exists() && !fPath.isFile() ) fPath.mkdir();

fPath = new File(path + "reportM\\");

// Legt den Report-Ordner an, falls er nicht existiert
if(!fPath.exists() && !fPath.isFile() ) fPath.mkdir();

File fName = new File(fPath.getAbsolutePath() + "\\" + name);

try {
FileWriter out = new FileWriter(fName);

out.write("[VERSCHOBENE DATEIEN:" + map.size() + "]\n");

if(map.size() == 0) out.write("-Es wurden keine Dateien verschoben-");

for(int i=0; i < map.size(); i++) {
out.write( map.get(i)+"\n" );
}

out.close();

return map.size();
} catch (Exception e) {
throw new DateienException(2);
}
}
[/code]

[java=181]
private void moveNToRK(File from, File to, HashMap<Integer, String> map, int filter, String[] details, final JProgressBar bar) throws DateienException {
/*
* FILTER:
* 0 = Keiner
* 1 = Dateiendung
*/

// Quelle und Ziel müssen Ordner sein
if(!from.isDirectory() || !to.isDirectory()) return;
if(from.getAbsolutePath().equals(to.getAbsolutePath())) return;

File[] fromList = from.listFiles();

for(int i=0; i < fromList.length; i++) {
if(fromList.getName().equals(to.getName())) break;
if(fromList.isFile()) {
if(filter == 1) {
boolean next = true;
for(int k = 0; k < details.length; k++) {
String d = details[k].toLowerCase().trim();
String c = fromList.getAbsolutePath().toLowerCase().trim();

if(c.endsWith(d)) {
next = false;
break;
}
}

if(next) continue;
}
String tmpName = fromList.getName();
String tmpTo = to.getAbsolutePath();
File move = new File(tmpTo + "\\" + tmpName);

File status = sameNameDetection(move, tmpTo);

if(status == null) break;

move = status;

fromList.renameTo(move);

map.put(map.size(), fromList.getAbsolutePath() + " --> " + move.getAbsolutePath());
Dateien.ANZAHL++;
} else if(fromList.isDirectory()) {
File newDir;
if(filter==0)
newDir = new File(to.getAbsoluteFile() + "\\" + fromList.getName() + "\\");
else
newDir = to;
File sourceDir = new File(from.getAbsolutePath() + "\\" + fromList.getName());

if(filter == 0)
if(!newDir.exists()) newDir.mkdir();

moveNToRK(sourceDir, newDir, map, filter, details, bar);

if(filter == 0) fromList.delete();
}
}
}
[/code]
 
danke für den link, aber ein verbesserungsvorschlag wäre mir lieber gewesen
 
Hallo TS,
noch schnell bevor es nach hause geht😉
Ich vermisse den SwingWorker???:L Ruf die Rekursion in der doInBackGround auf. Setzt dort den Progress und melde dich in der Gui als PropertyListener an um die PB zu aktualisieren.
BTW: Weißt du wieviele Daten du auswerten wirst? Ansonsten setze die PB doch einfach auf Intermediate:autsch:

Ciao velaluka
 
danke für den link, aber ein verbesserungsvorschlag wäre mir lieber gewesen
Das ist mir zuviel Code, aber hier mal eine Demo, wie man mit Threads arbeitet:
Java:
import java.awt.*;
import javax.swing.*;

public class ProgressBarDemo extends JPanel {
	private JProgressBar progressBar;
	private JLabel label;
	
	public ProgressBarDemo() {
		this.setLayout(new BorderLayout());
		progressBar = new JProgressBar();
		label = new JLabel("0%", JLabel.CENTER);
		this.add(label, BorderLayout.CENTER);
		this.add(progressBar, BorderLayout.SOUTH);
		new Thread(new MyWorkerThread()).start();
	}
	
	public static void main(String[] args) {
		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setBounds(0, 0, 500, 300);
		frame.setLocationRelativeTo(null);
		frame.getContentPane().add(new ProgressBarDemo(), BorderLayout.CENTER);
		frame.setVisible(true);
	}
	
	class MyWorkerThread implements Runnable {
		public void run() {
			for (int i=0; i<=100; i++) {
				//Hier mach was auch immer gemacht werden muss und vieeel Zeit kostet
				//aber Schritt für Schritt, damit die ProgressBar auch aktualisiert werden kann
				
				
				try {
					Thread.sleep(100);  //nur zur Demo
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				label.setText(i + "%");
				progressBar.setValue(i);
			}
		}
	}
}
 
Java:
        Thread moving = new Thread() {
            @Override
            public void run() {
                try {
                    moveNToRK(from, to, map, filter, details, null);
                    interrupt();
                } catch (DateienException e) {
                    e.printStackTrace();
                }
            }
        };
        
        Thread pBar = new Thread() {
            public void run() {
                while(true) 
                    bar.setValue(ANZAHL);
            };
        };
        
        moving.start();
        pBar.start();
Das sieht ziemlich kaputt aus. Was soll das interrupt()? Wann wird der pBar-Thread beendet? Wozu 2 Threads?
Schmeiß das weg, nimm dir das Swingworker-Beispiel und fang damit nochmal an.
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben