Event Propagation und Frame

Fragen zu Tkinter.
Antworten
Georg
User
Beiträge: 18
Registriert: Mittwoch 29. August 2007, 17:01

Ich würde gern ausnutzen, dass Tastendrücke ans Eltern-Widget weitergereicht werden. Seltsamerweise wird Frame dabei übersprungen. Ich erhalte pro Tastendruck nur zwei Meldungen:
label caught a key
toplevel caught a key

Code: Alles auswählen

from tkinter import *

def toplevelHandler( event ) :
    print( 'toplevel caught a key' )
def frameHandler( event ) :
    print( 'frame caught a key' )
def labelHandler( event ) :
    print( 'label caught a key' )

toplevel = Toplevel()
toplevel.bind( '<Key>', toplevelHandler )

frame = Frame( toplevel )
frame.bind( '<Key>', frameHandler )
frame.pack()

label = Label( frame, text='*****************' )
label.bind( '<Key>', labelHandler )
label.pack()

label.focus_set()

mainloop()
Für einen Funktionstest für Frame habe ich den Fokus verstellt und erhalte erwartungsgemäß
frame caught a key
toplevel caught a key

Code: Alles auswählen

... siehe oben ...
#label.focus_set()
frame.focus_set()

mainloop()
Was mache ich falsch?
Benutzeravatar
daemonTutorials
User
Beiträge: 171
Registriert: Sonntag 6. Februar 2011, 12:06
Kontaktdaten:

"frame" ist ein Kind-Element von Toplevel. Sie unterscheiden sich nur dadurch, dass Frame eine Unterteilung in einem Fenster ist. Versuch mal einen 2. Frame zu erstellen.

Maik
LG Maik
Georg
User
Beiträge: 18
Registriert: Mittwoch 29. August 2007, 17:01

Danke.
Ich habe also zwei Frames in Toplevel eingefügt. Hast du das gemeint ?
Am Ergebnis hat sich aber nichts geändert :

$ p3 eventPropagation.py
label caught a key
toplevel caught a key
label caught a key
toplevel caught a key

Code: Alles auswählen

from tkinter import *

def toplevelHandler( event ) :
    print( 'toplevel caught a key' )
def frameHandler( event ) :
    print( 'frame caught a key' )
def labelHandler( event ) :
    print( 'label caught a key' )

toplevel = Toplevel()
toplevel.bind( '<Key>', toplevelHandler )

frame = Frame( toplevel )
frame.bind( '<Key>', frameHandler )
frame.pack()

frame1 = Frame( toplevel )
frame1.pack()

label = Label( frame, text='*****************' )
label.bind( '<Key>', labelHandler )
label.pack()

label.focus_set()
#frame.focus_set()

mainloop()
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo Georg

Warum möchtest du den event an das Frame weitergeben?

Gruß wuf :wink:
Take it easy Mates!
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hier noch etwas zum herum experimentieren:

Code: Alles auswählen

from tkinter import *

def app_win_handler(event):
    print('app_win caught a key')

def toplevel_handler(event) :
    print('toplevel caught a key')
    
    #~~ Das fokusierte Widget befindet sich in Frame-A
    if str(frame_a) == str(event.widget.winfo_parent()):
        print('frame group-A caught a key')
        
    #~~ Das fokusierte Widget befindet sich in Frame-B
    if str(frame_b) == str(event.widget.winfo_parent()):
        print('frame-group-B caught a key')

def frame_handler(event) :
    print('frame caught a key')
    
def label1_handler(event) :
    print('label-1 caught a key')
        
def label2_handler(event) :
    print('label-2 caught a key')

def label3_handler(event) :
    print('label-3 caught a key')

def label4_handler(event) :
    print('label-4 caught a key')

def label5_handler(event) :
    print('label-5 caught a key')
    
app = Tk()
app.bind('<Key>', app_win_handler)
app.title('Haupt-Fenster')

#~~ Applikations globale Konfigurationen
#   WICHTIG: Die Optionsnamen sind ein Gemisch von klein & gross geschriebenen
#            Buchstaben! (Entspricht nicht genau der Schreibweise wie bei einer
#            widget-Konfiguration)
app.option_add("*Label.highlightColor", 'red')
app.option_add("*Label.highlightThickness", 1)

toplevel = Toplevel(takefocus=1)
toplevel.bind('<Key>', toplevel_handler)
toplevel.title('Toplevel-Fenster')

frame_a = Frame(toplevel, bg='khaki')
frame_a.bind( '<Key>', frame_handler )
frame_a.pack(fill='x')

frame_b = Frame(toplevel, bg='yellowgreen')
frame_b.bind( '<Key>', frame_handler )
frame_b.pack(fill='x')

label1 = Label(frame_a, text='Label-1 in frame-A', bg=frame_a['bg'])
label1.bind('<Key>', label1_handler)
label1.pack(fill='x')

label2 = Label(frame_a, text='Label-2 in frame-A', bg=frame_a['bg'])
label2.bind('<Key>', label2_handler)
label2.pack(fill='x')

label3 = Label(frame_b, text='Label-3 in frame-B', bg=frame_b['bg'])
label3.bind('<Key>', label3_handler)
label3.pack(fill='x')

label4 = Label(frame_b, text='Label-4 in frame-B', bg=frame_b['bg'])
label4.bind('<Key>', label4_handler)
label4.pack(fill='x')

label5 = Label(toplevel, text='Label-5 not in frame', bg='powderblue')
label5.bind('<Key>', label5_handler)
label5.pack(fill='x')

#~~ Aktiviert das Toplevelfenster
toplevel.transient(app)

#~~ Test-1
label1.focus_set()
#~~ Test-2
#label2.focus_set()
#~~ Test-3
#label3.focus_set()
#~~ Test-4
#label4.focus_set()
#~~ Test-5
#label5.focus_set()

app.mainloop()
Gruß wuf :wink:
Take it easy Mates!
Georg
User
Beiträge: 18
Registriert: Mittwoch 29. August 2007, 17:01

@wuf 1
Der Fokus läge bei einer Listbox. Sie verarbeitet die Pfeiltasten. Außen herum ein Frame, der außer der Listbox ein paar Labels enthält. Ein Label wird vom Frame aus geändert, mit Zifferntasten und BackSpace. Außen herum ein Toplevel, das auf Buchstaben wartet und dementsprechend den Fokus zu anderen Frames verschiebt oder Dialoge aufruft. Außerdem würde das Toplevel für alle übrigen Tastendrücke eine Fehlermeldung erzeugen.
@wuf 2
Dankeschön.
Also bleibt es dabei, dass der Frame nichts mitbekommt.
Meine jetzige Lösung entspricht deinem toplevel_handler .

Gruß Georg
Antworten