Entwickler-Ecke
WinForms - Selbstgebaute Progressbar richtig füllen
Garzec - Di 19.07.16 13:49
Titel: Selbstgebaute Progressbar richtig füllen
Hallo,
ich habe mit meinem Anfängerhalbwissen eine runde Progressbar in einem Usercontrol gebastelt. Google sei Dank. Der Kreis füllt sich auch prima, ich stehe nur grade vor dem Problem, diesen über meine Variable zu füllen.
Ich benutze einen MP3Player über die winmm.dll, der Kreis soll also passend zum Lied gefüllt werden. Jetzt habe ich ein ulong Property, das die Dauer des Liedes berechnet bzw. hält.
Folgende Methoden füllen den Kreis
C#-Quelltext
1: 2: 3: 4: 5: 6: 7:
| private void ProgressUpgrade(object fortschritt) { progessBarCustom.Invoke((MethodInvoker)delegate { progessBarCustom.UpdateProgress(Convert.ToInt32(fortschritt)); }); } |
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| private void ProgressBarFuellen() { Task.Run(() => { for (int i = 0; i < 101; i++) { new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(ProgressUpgrade)).Start(i); System.Threading.Thread.Sleep(50); } }); } |
Zu meiner Frage:
Da sich der Kreis momentan noch von alleine füllt, muss er sich jetzt in Abhängigkeit zur Lieddauer füllen. Wenn ich versuche,
C#-Quelltext
1:
| System.Threading.Thread.Sleep(Convert.ToInt32(datei.Duration / 100)); |
zu schreiben, ist das glaube ich 1. Blödsinn und 2. kommt eine Format Exception auf.
Weiß jemand, wie ich die Dauer nun dort einpflege =?
Ralf Jansen - Di 19.07.16 15:26
Anstatt i einfach hoch zu zählen berechne i doch einfach. Du solltest doch Gesamtlaufzeit und aktuellen Zeitpunkt im Titel irgendwie rausbekommen können und daraus i berechnen.
Aus deiner
Vorschleife For-Schleife wird dann halt einfach ein while oder do while Konstrukt.
Pseudocode
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| double runtime = ERMITTLELAUFZEIT(); double currenttime = 0.0;
while(currenttime < runtime) { ProgressUpgrade(currenttime/runtime * 100); System.Threading.Thread.Sleep(50); currentime = ERMITTLEZEITPUNKT(); } |
Garzec - Di 19.07.16 15:38
Hey,
vielen Dank für die Antwort. Die Laufzeit kann ich berechnen, mithilfe dieser Berechnung
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| public ulong Duration { get { StringBuilder builder = new StringBuilder(128); mciSendString("status mediafile length", builder, 128, IntPtr.Zero); return Convert.ToUInt64(builder.ToString()); } } |
Den aktuellen Zeitpunkt der Datei kann man aber meines Wissens nicht bestimmen. Genau da liegt mein Problem :P
Ralf Jansen - Di 19.07.16 15:47
laut google sollte es "status mediafile position" sein.
Th69 - Di 19.07.16 15:50
Hallo Garzec,
Thread-Sleep ist zum einen sehr ungenau (ca. 15ms Auflösung), so daß es passieren kann, daß die ProgressBar über 100 hinausläuft, aber der Hautpfehler bei deiner Berechnug ist, daß du die Dauer (duration) in Sekunden (höchstwahrscheinlich ;- ) hast, aber die Methode die Zeit in Millisekunden erwartet.
Besser wäre es m.E. wenn du dir beim Liedstart die aktuelle Zeit holst (DateTime.Now) und dann in einem Timer (von ca. 1 Sekunde oder evtl. auch 500ms) wartest und dann den ProgressBar-Wert dort berechnest (über die aktuelle Zeit in Abhängigkeit der Dauer).
Edit: oder über den von Ralf Jansen vorgeschlagenen Wert.
Garzec - Di 19.07.16 20:29
Vielen Dank für eure Antworten.
Jetzt habe ich folgende Berechnungen:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| public ulong Duration { get { StringBuilder builder = new StringBuilder(128); mciSendString("status mediafile length", builder, 128, IntPtr.Zero); return Convert.ToUInt64(builder.ToString()); } }
public ulong LiedPosition { get { StringBuilder builder = new StringBuilder(128); mciSendString("status mediafile position", builder, 128, IntPtr.Zero); return Convert.ToUInt64(builder.ToString()); } } |
Und bei Aufruf dann folgende Methode:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| private void ProgressBarFuellen() { Task.Run(() => { ulong laufzeit = datei.Duration; ulong aktuelleZeit = 0; while (aktuelleZeit < laufzeit) { ProgressUpgrade(aktuelleZeit / laufzeit * 100); System.Threading.Thread.Sleep(50); aktuelleZeit = datei.LiedPosition; } }); } |
Beim Start taucht tatsächlich eine Exception auf (falsches Format), obwohl das richtige Zeitformat wiedergegeben wird. Bei einem Lied von 4min 31sek. wird eine Zahl von ~~~27000 geliefert. Das sollten also die Millisekunden sein.
Nun frage ich mich, was ihn an dem Format stört =?
Ralf Jansen - Di 19.07.16 21:03
Zitat: |
Nun frage ich mich, was ihn an dem Format stört =? |
Es hilft uns wenn du sagst wo. Und wie das Format wirklich aussieht.
C#-Quelltext
1:
| aktuelleZeit / laufzeit * 100 |
Das wird nicht funktionieren. Wenn die beiden Variablen Ganzzahlen sind ist das Ergebnis auch immer eine ganze Zahl und da aktuelleZeit immer kleiner Laufzeit ist kommt da immer 0 raus (oder im speziellen Sonderfall halt 100). Du musst schon mit Fließkommazahlen rechnen so wie in meinem Beispiel oder so rechnen das auch eine sinnvolle Division möglich ist.
Beispiel mit Ganzzahldivision
Quelltext
1: 2:
| 999/1000 * 100 = 0 weil 999/1000 = 0 ist mit Rest 999 (999*100)/1000 = 99 Rest 900 aber der ist hier egal ;) |
Bitte nicht heimlich
crossposten [
https://www.spieleprogrammierer.de/16-eingabe-audio-physik-netzwerk-scripting-und-ki/25850-dauer-einer-mp3-datei-ermitteln/].
Garzec - Di 19.07.16 22:14
Sorry, der Post ist zwar noch nicht alt, da ging es aber noch um die Ermittlung der Dauer einer Datei :) Jetzt geht es ja um das Füllen einer Progressbar über die Zeiten
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!