Seite 1 von 2
[gelöst] eingefrorene ProgessBar
Verfasst: 14. September 2009 13:15
von nane
Hallo,
ich möchte eine ProgressBar in der Statusleiste anzeigen, wenn ich auf einen Button drücke und diese soll während der weiteren Abarbeitung laufen (also ein Laufbalken, kein fester Wert, mit setRange(0,0)).
In etwa so:
Code: Alles auswählen
void Widget::startMeasurement()
{
progressBarShow();
//..... Messung durchführen
progressBarRemove();
}
Was aber passiert ist, dass sie angezeigt wird, während der Messung stehen bleibt, also eingefroren ist, und dann wie gewollt wieder ausgeblendet wird.
Wie kann ich es hinbekommen, dass sich die Anzeige wie gewünscht bewegt?
Gruß
Verfasst: 14. September 2009 14:26
von Curtis Newton
http://doc.trolltech.com/4.5/qcoreappli ... ssEvents-2 vergessen? Noch schöner wäre es natürlich, die Verarbeitung in einen extra Thread zu packen!
C.
Verfasst: 14. September 2009 15:43
von nane
QCoreApplication::processEvents(); funktioniert leider nicht, obwohl ichs mehrmals zwischen show und remove eingestreut habe. Kann es vielleicht auch mit Sleep() zusammenhängen, da dies während der Messung verwendet wird?
Ansonsten würde mich die Thread Version interessieren: Muss ich dazu die Messung in einen Thread packen und dann zwischen show und remove start() ausführen?
Verfasst: 14. September 2009 15:53
von Curtis Newton
nane hat geschrieben:QCoreApplication::processEvents(); funktioniert leider nicht, obwohl ichs mehrmals zwischen show und remove eingestreut habe. Kann es vielleicht auch mit Sleep() zusammenhängen, da dies während der Messung verwendet wird?
Ansonsten würde mich die Thread Version interessieren: Muss ich dazu die Messung in einen Thread packen und dann zwischen show und remove start() ausführen?
Tja, ohne Code kann man wenig sagen. Und Du aktualisierst auch die Progressbar (also setzt sie auf einen neuen Wert)?
Zum Thread - hmmm, mal als Idee. Den Start des Threads packst Du in eine Funktion. Hier erstellst Du auch die Progressbar und zeigst sie. Vom Thread sendet Du dann jeweils ein Signal, wenn die Progressbar eines weiter gesetzt werden soll (oder Du sendest als Parameter direkt den Wert, den sie annehmen soll).
Wenn der Thread fertig ist, sendet er eine Nachricht an den Hauptthread, dass er fertig ist. Und dieser löscht die Bar wieder.
C.
Verfasst: 14. September 2009 15:57
von nane
wenn ich sie aktualisiere (neuen Wert setzen) funktioniert alles, aber ich brauche für die Messung einen Laufbalken und der soll sich ja einfach nur bewegen, was er aber leider nicht tut.
Verfasst: 14. September 2009 16:07
von Curtis Newton
nane hat geschrieben:wenn ich sie aktualisiere (neuen Wert setzen) funktioniert alles, aber ich brauche für die Messung einen Laufbalken und der soll sich ja einfach nur bewegen, was er aber leider nicht tut.
Ich gebe jetzt mal genauso viele Informationen wie Du:
C.
Verfasst: 14. September 2009 16:16
von nane
ich kanns gerne nochmals erklären:
wie in meiner ersten nachricht schon zu lesen war, brauche ich einen laufbalken als progressbar und keinen der mir 49% oder sowas angibt sondern einen, der mit setRange(0,0) immer weiterläuft.
wenn ich während der messung ein paar prozentangaben setze progressBar->setValue(x) werden diese richtig angezeigt, aber wie schon mehrfach gesagt, will ich das so nicht.
wenn ich also progressBar->show() und davor oder danach progressBar->setRange(0,0) vor der Messung und progressBar->hide() nach der Messung schreibe, erscheint das ding bewegt sich aber keinen milimeter.
Verfasst: 14. September 2009 16:39
von Curtis Newton
nane hat geschrieben:ich kanns gerne nochmals erklären:
wie in meiner ersten nachricht schon zu lesen war, brauche ich einen laufbalken als progressbar und keinen der mir 49% oder sowas angibt sondern einen, der mit setRange(0,0) immer weiterläuft.
Wie weiterläuft? So hin und her oder was? Verstehe ich nicht.
Scheibar hast Du zwei Probleme: ein geeignetes Widget und wie dieses aktualisieren?!?!
C.
Verfasst: 14. September 2009 16:48
von nane
fast richtig

ich habe EIN problem, aktualisieren muss man die QProgressBar eigentlich nicht, sie bleibt halt einfach stehen, was sie nicht tut ohne messung.
das richtige widget ist es aber dennoch
http://doc.trolltech.com/4.5/qprogressbar.html#details
If minimum and maximum both are set to 0, the bar shows a busy indicator instead of a percentage of steps
Verfasst: 15. September 2009 08:31
von Curtis Newton
Geht doch:
Code: Alles auswählen
include <QProgressBar>
#include <Windows.h>
int main( int argc, char **argv )
{
QApplication a( argc, argv );
QProgressBar bar;
bar.resize(300,50);
bar.setMinimum(0);
bar.setMaximum(0);
bar.show();
for(int i=0; i<50; i++)
{
Sleep(100);
QCoreApplication::processEvents();
}
return a.exec();
}
C.
Verfasst: 15. September 2009 09:27
von nane
Schonmal zwischendurch vielen dank für deine mühe. So langsam nähern wir uns dem Problem
setz mal Sleep auf 1000 oder 3000, da das die Größenordnung ist, die ich für die Messung brauche, dann wirst du starkes Ruckeln oder Einfrieren während Sleep festellen und das will flüssig haben.
Verfasst: 15. September 2009 09:45
von Curtis Newton
nane hat geschrieben:Schonmal zwischendurch vielen dank für deine mühe. So langsam nähern wir uns dem Problem
setz mal Sleep auf 1000 oder 3000, da das die Größenordnung ist, die ich für die Messung brauche, dann wirst du starkes Ruckeln oder Einfrieren während Sleep festellen und das will flüssig haben.
Tja, wie gesagt, Threads.
C.
Verfasst: 15. September 2009 14:37
von nane
Ich habe mein Glück jetzt mit Threads versucht, was leider auch noch nicht funktioniert.
threads.h
Code: Alles auswählen
#include <QtGui>
#include "definitions.h"
class SingleMeasThread : public QThread
{
public:
void run();
};
threads.cppCode: Alles auswählen
#include "threads.h"
#include <windows.h>
void SingleMeasThread::run()
{
qDebug() << "vorher\n";
for(int i=0; i<10;i++)
{
qDebug() << i << "drin\n";
Sleep(500);
}
qDebug() << "nachher\n";
exec();
}
another.cppCode: Alles auswählen
void Meas::startMeasurement()
{
SingleMeasThread single;
connect(&single,SIGNAL(started()),this,SLOT(progressBarShow()));
connect(&single,SIGNAL(finished()),this,SLOT(progressBarRemove()));
single.start();
qDebug() << "startmeas\n";
}
qDebug gibt startmeas aus aber weder "vorher", "drin" noch "nachher". Außerdem kommt es zu Abstürzen mit Speicherzugriffsverletzungen, die bei jedem Start des Programms anders sind.
Kann das sein, dass ich irgendwas grundlegenes bei den Threads falsch mache? Habe damit noch nie gearbeitet.
Verfasst: 15. September 2009 15:36
von nane
So jetzt funktionierts, mal sehen wie lange und mal sehen ob wirklich alles klappt.
Mein Fehler war in another.cpp: SingleMeasThread darf dort nicht instanziiert werden, da das Objekt gelöscht wird, wenn startMeasurement verlassen wird und das ist bevor die Messung beendet ist. Also zeigten die Zeiger, die per connect übergeben wurden, an undefinierte Stellen -> Speicherzugrifffehler.
Kann mir dennoch jemand erklären wann man exec() in run() schreibt und wann nicht? Ist das vielleicht wenn man eine Endlosschleife erstellen will und auf Signale wartet und wenn man eine feste Anzahl an Befehlen ausführt braucht man das nicht?
Also nochmals vielen Dank an Curtis Newton!!!
Gruß
Verfasst: 15. September 2009 15:55
von RHBaum
run() muss man immer schreiben !
das ist die trheadproc, die durch den thread gestartet wird ... pure virtual, also musst ueberschreiben ....
exec wenn du es nutzen willst, solltest du unmittelbar im run aufrufen.
Dadurch geht der thread sofort in eine eventschleife und harrt der ereignisse die da kommen. Werden dann signale geworfen, die du in deinem thread zu slots connected hasst ... kriegt dein threads die entsprechenden events und springt in die dazugehorige slot-funktion.
Braucht man also, wenn der erstellte thread auf signale oder events hoeren soll (die meist vom anderen trhead aus gefeuert werden. aus dem selben thread heraus kann man besser durch direkte aufrufe ersetzen und sich die eventschleife komplett sparen) .
Nur der thread, der auf Signale reagieren (empfangen) soll, braucht die eventloop. Wenn du events / signale zum mainthread schicken willst, von einem thread aus, brauchst ned loopen, sondern kannst die events / Signale direkt feuern, der mainthread / guithread ist eh geloopt (QApplication::exec() )
Man kann damit ziemlich elegant threadwechsel hinbekommen.
Ciao ....