[gelöst] eingefrorene ProgessBar

Alles rund um die Programmierung mit Qt
nane
Beiträge: 11
Registriert: 31. Juli 2009 23:16

[gelöst] eingefrorene ProgessBar

Beitrag 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ß
Zuletzt geändert von nane am 16. September 2009 10:37, insgesamt 1-mal geändert.
Curtis Newton
Beiträge: 122
Registriert: 11. Juni 2008 18:39

Beitrag 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.
nane
Beiträge: 11
Registriert: 31. Juli 2009 23:16

Beitrag 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?
Curtis Newton
Beiträge: 122
Registriert: 11. Juni 2008 18:39

Beitrag 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.
nane
Beiträge: 11
Registriert: 31. Juli 2009 23:16

Beitrag 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.
Curtis Newton
Beiträge: 122
Registriert: 11. Juni 2008 18:39

Beitrag 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.
nane
Beiträge: 11
Registriert: 31. Juli 2009 23:16

Beitrag 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.
Curtis Newton
Beiträge: 122
Registriert: 11. Juni 2008 18:39

Beitrag 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.
nane
Beiträge: 11
Registriert: 31. Juli 2009 23:16

Beitrag 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
Curtis Newton
Beiträge: 122
Registriert: 11. Juni 2008 18:39

Beitrag 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.
nane
Beiträge: 11
Registriert: 31. Juli 2009 23:16

Beitrag von nane »

Schonmal zwischendurch vielen dank für deine mühe. So langsam nähern wir uns dem Problem :wink:
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.
Curtis Newton
Beiträge: 122
Registriert: 11. Juni 2008 18:39

Beitrag von Curtis Newton »

nane hat geschrieben:Schonmal zwischendurch vielen dank für deine mühe. So langsam nähern wir uns dem Problem :wink:
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.
nane
Beiträge: 11
Registriert: 31. Juli 2009 23:16

Beitrag 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.cpp

Code: 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.cpp

Code: 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.
nane
Beiträge: 11
Registriert: 31. Juli 2009 23:16

Beitrag 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ß
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag 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 ....
Antworten