[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