[python-users] Tkinterprobleme
Thomas Lenarz
Thomas.Lenarz at netcologne.de
Do Apr 19 20:45:05 CEST 2007
prof. dr. peter ziese schrieb:
Hallo Peter,
Deine Frage hat mich gereizt, einmal grundsätzlich darauf antworten.
Auch wenn es nicht Python-spezifisch ist. Vor ca. 12 (?) Jahren haben mich ähnliche
überraschende Effekte im Rahmen der OS/2-Presentation-Manager-Programmierung
beschäftigt. Also los...
> 1) Warun ist das so?
Zumindest alle GUI-Systeme, die ich kenne, arbeiten intern nachrichtenbasiert. Wenn man
z.B. Win32 direkt in C programmiert, hat man damit auch direkten Kontakt.
Alle GUI-Programme melden sich zunächst in irgendeiner Form beim grafischen System
(Windows, Presentation-Manager etc.) an. Das System hat eine Nachrichten-
Warteschlange, in die alle möglichen Ereignisse eingestellt werden. Die Ereignisse besitzen
ein identifizierendes Merkmal (Maus hat sich bewegt, Maustaste wurde gedrückt usw.), viele
weitere Parametern und den Adressaten, der letztendlich (etwas vereinfacht beschrieben)
Dein Programm ist.
Das Herz jeden Programmes ist eine Schleife, die ständig Nachrichten aus der Nachrichten-
Wartenschlange entnimmt und diese dann an eine Call-Back-Prozedur weitereicht.
while (GetMessage(...) )
{
DispatchMessage(..)
}
So etwas ähnliches müsste auch in TK's mainloop() verpackt sein.
In der Call-Back-Prozedur wird dann "die eigentliche Arbeit" gemacht. Letztendlich
entspricht die Call-Back-Prozedur den Methoden, die Du bei Tkinter mittels bind() an
bestimmte Ereignisse binden kannst. Immer wenn das Ereignis kommt (Mouse-Click auf
Button) dann wird eine bestimmte Methode aufgerufen.
Nun ist die Call-Back-Prozedur viel allgemeiner, weil sie alle möglichen Ereignisse
verarbeitet. Auch solche, die Dich gar nicht interessieren. Diese Ereignisse werden dann
von der selbstprogrammierten Call-Back-Prozedur an eine vom System angebotene Call-
Back-Prozedur weitergereicht, die sich um die Nachricht kümmert.
Nun komme ich endlich zu Deiner "Warum ist das so?"-Frage : Eine von den möglichen
Nachrichten ist (in Windows) die WM_PAINT-Nachricht. Sie wird immer dann vom System
an ein Programm gerichtet, wenn der Inhalt eines Fensters neu gezeichnet werden soll. Das
passiert andauernd z.B.: auch dann wenn ein Fenster zeitweise durch ein anderes verdeckt
war. Das Zeichnen Deines Fensterinhaltes, den Du ja auf das Canvas gemalt hast
übernimmt irgendwo TK für Dich.
Wie sieht nun Dein Programm aus?
-Du bereitest zunächst alles vor und malst intern Grafiken auf eine Leinwand (Canvas). TK
macht das auch und berücksichtigt auch die sleep's, die Du eingebaut hast. Währenddessen
stauen sich vermutlich schon WM_PAINT (oder ähnliche)-Nachrichten in der Warteschlange
an.
-Dann betrittst Du Deine Nachrichtenschleife mittels mainloop() und gibtst dem System die
Chance die Nachricht(en) zum Zeichnen zu verarbeiten und plöpp, Deine Grafik erscheint
auf einmal und ohne die Pausen, die Du eingebaut hast.
Der von Michael vorgeschlagene Timer-Callback ist aus meiner Sicht auch die richtige
Lösung für Dein Problem. Er gibt Dir die Möglichkeit Deinen Vorgang des "Malens" in den
Kontext der mainloop zu verlagern.
Du malst also einen Strahl und sagst dem System: Rufe mich bitte nach einer gewissen Zeit
zurück, dann malst Du den nächsten Strahl usw.. Dadurch dürftest Du dann schön animiert
den Vorgang verfolgen können. Im Windows würde das der WM_TIMER-Nachricht
entsprechen.
Ein interessantes Experiment wäre es dann auch tatsächlich einmal, längere Warteschleifen
in solche an Ereignisse gebundene Methoden einzubauen. Im OS/2-Presentation-Manager
und zumindest in älteren Windows-Versionen hatte das den Effekt, dass für den Zeitraum
der Warteschleife die gesamte (!) Oberfläche eingefroren war. Das deswegen, weil alle
Programme sich aus derselben System-Nachrichten-Warteschlange bedienen. Wenn ein
"böses" Programm nun seine Nachrichten nicht mehr abholt, gibt es Verkehrsstau und alle
anderen warten auch. (Ich weiß allerdings nicht wie es in TK ist. Habe es nie probiert.)
Das ist jetzt viel länger geworden, als ich eigentlich wollte. Ich hoffe, ich werde jetzt nicht
kiloweise mit Tomaten beworfen, da es auch noch etwas OT war, da nicht python-
spezifisch. Mir hilft es aber manchmal sehr über die Grundlagen nachzudenken, um
bestimmte Dinge auf höherer Ebene zu verstehen.
Viele Grüße
Tommes
--
mailto:Thomas.Lenarz at netcologne.de
mailto:Thomas.Lenarz at koeln.de
Mehr Informationen über die Mailingliste python-users