Wenn ich das richtig verstanden habe, dann werden Events nur von dem Widget ausgeführt über welchem die Maus steht, aber nur wenn kein anderes Widget fokusiert ist.
Wenn ein Widget fokusiert sein sollte, dann sollten die Events dort ausgeführt werden, oder ?
So weit die Theorie, nun habe ich aber das bekannte Problem, dass wenn ich ein paar dutzend Widget auf einen Frame packe, den Frame ja nicht mehr mit der Maus drüber fahren und ihn indirekt fokusieren kann.
Also bleibt der mir nur bekannte weg ihn direkt fokusieren zu lassen mit takefocus=True und dann der ".focus_set()"-Methode.
Dies funktioniert aber nur im Windows, unter allen anderen System werden die Events dennoch nicht ausgelöst, obwohl die entsprechenden Widgets manuell fokusiert wurden und über die ".focus_get()" Methode auch als selektiert ausgegeben werden.
Wo liegt also das Problem, habe ich in der Theorie da was falsch verstanden ?
Ziel des ganzen ist es, auf einer Oberfläche mehrere Scrollbars, Spinboxen und Scales per Mausscrollradbedienen zu können. Spinboxen und Scales kein Problem, aber halt die Scrollbars, da ich den Scroll Event auf das gesamte Widget legen möchte und allen unteren Widgets.
Folgendes hatte ich mir ausgedacht und ich bin mir ziemlich sicher, das dies auch schöner geht:
Code: Alles auswählen
#Widgets bei denen auf keinen Fall der Focus verloren gehen darf
_dont_select = [ttk.Entry]
#Widgets auf den der Focus manuell gelegt werden soll
_do_select = [ScrolledLabelFrame, ttk.Scale, tkinter.Spinbox]
#Ein Event, welches mit bind_all("<Motion>", ...) auf das gesamte Widget gelegt wird
def select_scrolls(event):
#Das Widget auf dem die Maus steht ermitteln
widget = event.widget
while widget is not None and type(widget) is not str:
#Prüfen ob eine Fokusierung erfolgen soll
if any(isinstance(widget, w) for w in _do_select):
#Prüfen ob das aktuell fokusierte Widget abgewählt werden darf
if not any(isinstance(widget.focus_get(), w) for w in _dont_select):
widget.focus_set()
break
#Übergeordnetes Widget setzen und darauf prüfen
widget = widget.master
Die Scrollevents sehen dann so aus:
Code: Alles auswählen
...
self.bind("<MouseWheel>", self.scroll)
self.bind("<Button-4>", self.scroll)
self.bind("<Button-5>", self.scroll)
def scroll(self, event):
if event.num == 5 or event.delta < 0:
self.canvas.yview_scroll(1, "unit")
elif event.num == 4 or event.delta > 0:
self.canvas.yview_scroll(-1, "unit")