Seite 1 von 1
Gleichmäßig animierter Pausencursor
Verfasst: 6. April 2009 14:49
von DanHarrow
Hallo zusammen!
Ich habe folgendes Problem: ich möchte gerne, während mein Programm busy ist, einen dauerhaft animierten Pausencursor sehen.
1. Ansatz: QApplication::setOverrideCursor mit dem Startcursor aufrufen, dann einen QTimer erzeugen und dessen timeout-SIGNAL mit einem eigenen animate-SLOT connecten, in dem dann QApplication::changeOverrideCursor immer das nächste Cursorbild setzt.
Problem: funktioniert nur, wenn das Programm nicht busy ist. Die EventLoop scheint es nicht zu schaffen, den Timer während der busy-Phase anzusprechen
2. Ansatz: neue Klasse von QThread abgelitten, und in deren run-Methode dann einen Timer gebaut mit den gleichen SIGNAL-SLOT-Verbindungen wie in 1. Leider ist auch hier die Animation nur dann von Dauer, wenn das Programm nicht busy ist. Das hätte ich zumindest hier in einem parallel laufenden Thread nicht erwartet. ThreadPriority ist auf höchste Stufe gestellt (TimeCriticalPriority ).
Ich baue mein Programm mit dem Microsoft-Visual-Studio 2008 Express Edition, MultiThread ist latürnich aktiviert
Mache ich einen grundlegenden Fehler? Oder kann QApplication::changeOverrideCursor nichts machen, wenn der Hauptthread busy ist?
Vielen Dank schon mal für die zahlreichen Antworten!
Dan

Verfasst: 6. April 2009 14:55
von Willi2793
Hast Du denn in dem QThread auch einen Eventloop?
Ansonsten kannst Du den Cursor an sich animiert machen. Dann bruchst Du das gar nicht selber steuern. (Allerdings weiß ich leider nicht wie, aber ich habe schon animierte Cursor geshen)
Verfasst: 6. April 2009 15:08
von DanHarrow
Jupp: hier der Code
Code: Alles auswählen
void MyThread::run
//------------------------------------------------------------
//
//------------------------------------------------------------
()
{
m_animate = false;
QTimer timer;
timer.setInterval(100);
connect(&timer, SIGNAL(timeout()), this, SLOT(doAnimate()));
timer.start();
exec();
}
Mit an sich animierten Cursorn (.ani) habe ich es bereits probiert -- leider kann man QCursors (und damit QPixmap) nicht mit .ani-Dateien erzeugen.
Dan
Verfasst: 6. April 2009 15:15
von Willi2793
Ein ähnliches Problem hatte ich auch einmal. Ich hatte das Gefühl das die run-methode des Threads noch im Kontext des aufrufenden Threads ausgeführt wird. Meine Lösung war dann folgendes:
Dann folgenden Slot:
Code: Alles auswählen
void MyThread::startSlot()
{
m_animate = false;
QTimer* timer = new QTimer();
timer->setInterval(100);
connect(timer, SIGNAL(timeout()), this, SLOT(doAnimate()));
timer->start();
}
und den nach dem thread.start() im Hauptthread per signal aufrufen.
Und bitte für eigenen Code die Code-tags hier verwenden
Verfasst: 6. April 2009 15:28
von pfid
Btw, wenn du einen Thread hast, wozu brauchst du nen Timer?
Code: Alles auswählen
void Thread::run()
{
while (notQuit)
{
waitCond.wait(&mutex, 100);
doAnimate();
}
}
Zum ursprünglichen Problem: keine Ahnung. Die ganze Konstruktion erscheint mir aber schräg. Aber liegt vermutlich daran, dass ich dein Problem noch nicht vollständig verstehe, und auch keine Ahnung von Cursor in Qt habe.
In QThread darf man übrigens nichts GUI-spezifisches machen, keine Ahnung in wie weit das hier der Fall wäre.
Verfasst: 6. April 2009 15:38
von DanHarrow
pfid hat geschrieben:
Zum ursprünglichen Problem: keine Ahnung. Die ganze Konstruktion erscheint mir aber schräg. Aber liegt vermutlich daran, dass ich dein Problem noch nicht vollständig verstehe, und auch keine Ahnung von Cursor in Qt habe.
Naja, war erst einfach: nur ein Timer mit SLOT verbunden. Leider verrichtet der Timer nicht so seine Arbeit, wie ich es erwartet hätte. Daher dann der Umstieg auf den QThread.
pfid hat geschrieben:
In QThread darf man übrigens nichts GUI-spezifisches machen, keine Ahnung in wie weit das hier der Fall wäre.
Jupp, das Ändern des Cursors schafft der QThread aber einwandfrei ...
Verfasst: 6. April 2009 15:47
von DanHarrow
Willi2793 hat geschrieben:
... und den nach dem thread.start() im Hauptthread per signal aufrufen.
Hm, macht leider keinen Unterschied ...
Verfasst: 6. April 2009 15:57
von solarix
Was macht "doAnimate()"? Was macht dein Hauptthread, wenn er "busy" ist?
Verfasst: 6. April 2009 16:47
von 000Hunter000
Sag mal kann es sein das wenn dein Programm busy ist du einfach im hauptthread irgendwelche Berechnungen oder sonnstwas laufen lässt und so einfach den EventLoop vom Hauptthread blockierst? Dann ist natürlich klar warum das signal vom timer nie ankommt...
EDIT:
ganz überlesen
Mache ich einen grundlegenden Fehler? Oder kann QApplication::changeOverrideCursor nichts machen, wenn der Hauptthread busy ist?
Naja wenn der Hauptthreadbusy ist und von deinem QTimer kommt halt ab und an ein signal kann es antürlich nicht verarbeitet werden weil nunja der Haupthread gerade mit was anderem beschäftigt ist. Das Signal wird erst zugestellt sobald du wieder zum event loop zurück kehrst.
Es gibt mehrere möglichkeiten:
1. Du rufst in deiner Funktion in der du diese Berechnungen laufen lässt ab und zu QApplication::ProcessEvents() auf. Kann aber ein bisschen heikel sein.
2. Meiner meinung nach schöner: Du verlagerst einfach das was auch immer so lange dauert in nen eigenen thread.
Verfasst: 7. April 2009 07:27
von DanHarrow
000Hunter000 hat geschrieben:
1. Du rufst in deiner Funktion in der du diese Berechnungen laufen lässt ab und zu QApplication::ProcessEvents() auf. Kann aber ein bisschen heikel sein.
Jupp! Das Programm, um das es hier geht, ist bereits aus dem letzten Jahrtausend, das nun eine neue GUI erhält. In den Tiefen der ca. 2500 Klassen überall QApplication::ProcessEvents() einzubauen, geht schlichtweg nicht. Ferner ist das Programm auch öfter busy im Aufruf von Fremdlibraries (z.B. DB-Anbindung), auf die ich leider gar keinen (Entwicklungs-)Einfluss habe.
000Hunter000 hat geschrieben:
2. Meiner meinung nach schöner: Du verlagerst einfach das was auch immer so lange dauert in nen eigenen thread.
Hm, das kann ich leider auch nicht machen, da während dieser unzähligen Berechungen ständig Updates an die GUI geschickt werden, die sich neu zu malen hat, und Maloperationen nur im Haupthread laufen können.
Verfasst: 7. April 2009 18:37
von 000Hunter000
DanHarrow hat geschrieben:000Hunter000 hat geschrieben:
1. Du rufst in deiner Funktion in der du diese Berechnungen laufen lässt ab und zu QApplication::ProcessEvents() auf. Kann aber ein bisschen heikel sein.
Jupp! Das Programm, um das es hier geht, ist bereits aus dem letzten Jahrtausend, das nun eine neue GUI erhält. In den Tiefen der ca. 2500 Klassen überall QApplication::ProcessEvents() einzubauen, geht schlichtweg nicht. Ferner ist das Programm auch öfter busy im Aufruf von Fremdlibraries (z.B. DB-Anbindung), auf die ich leider gar keinen (Entwicklungs-)Einfluss habe.
000Hunter000 hat geschrieben:
2. Meiner meinung nach schöner: Du verlagerst einfach das was auch immer so lange dauert in nen eigenen thread.
Hm, das kann ich leider auch nicht machen, da während dieser unzähligen Berechungen ständig Updates an die GUI geschickt werden, die sich neu zu malen hat, und Maloperationen nur im Haupthread laufen können.
die updates könntest du ja mit queued connections relisieren also entweder signals oder invokeMethod()