Innerhalb einer Funktion auslösenden Button ermitteln

Fragen zu Tkinter.
Antworten
Windy
User
Beiträge: 8
Registriert: Montag 17. Juli 2017, 11:45

Hallo,

hab da mal eine Abfängerfrage.

Kann man innerhalb einer Funktion ermitteln welcher Button die Funktion aufgerufen hat?
Ich möchte mit mehreren Buttons die gleiche Funktion aufrufen und innerhalb der Funktion den Button ermitteln.

Vielen Dank im Voraus
Windy
BlackJack

@Windy: Willst Du wirklich den Button ermitteln oder einen anderen Wert der damit zusammenhängt? Egal was, Du solltest es nicht in der Funktion/Methode ermitteln sondern als Argument übergeben lassen. Schau Dir mal `functools.partial()` an.
Windy
User
Beiträge: 8
Registriert: Montag 17. Juli 2017, 11:45

Code: Alles auswählen

from tkinter import *
from tkinter import ttk
import functools

def ereignis(nr):
    print(nr)

fenster = Tk()
a = Button(fenster, text='a', command=functools.partial(ereignis, '1'))
a.place(x=10, y= 10)

b = Button(fenster, text='b', command=functools.partial(ereignis, '2'))
b.place(x=50, y= 10)

fenster.geometry("2000x1000")
fenster.mainloop()
Sieht ungewöhnlich aus, funktioniert aber.

Dake für den Tipp

Gruß
Windy
Zuletzt geändert von Anonymous am Montag 17. Juli 2017, 18:33, insgesamt 2-mal geändert.
Grund: Aufrufklammern hinter `mainloop` gesetzt.
BlackJack

@Windy: Den Sternchen-Import und `place()` solltest Du loswerden. Mit Sternchen-Importen wird es schnell unübersichtlich so Namen herkommen und es besteht auch die Gefahr von Namenskollisionen. `place()` macht nur in sehr wenigen Fällen Sinn, und ansonsten im besten Fall nur Arbeit und im schlechten Fall unbenutzbare GUIs auf Systemen mit anderen Einstellungen.

Sind die Klammern für den Aufruf bei `mainloop()` beim kopieren verloren gegangen?
Windy
User
Beiträge: 8
Registriert: Montag 17. Juli 2017, 11:45

Hi,

dass mit dem mainloop() ist mir bis jetzt nie aufgefallen, da es keinen Fehler gab.

Das mit dem Sternchen ist bekannt. Versuche mich gerade etwas in Tkinter einzuarbeiten
und das sind Testscripte, die ich gerade schreibe.

Habe mir bereits die drei Möglichkeiten der Plazierung angesehen und mir ist persönlich
einfach die direkte Plazierung am sympathischsten.

Danke für die Hilfe
Gruß
Windy

PS. kann es sein, dass wenn Du als Admin in meinem Beitrag etwas änderst, dass ich dann keinen zugriff mehr auf eben diesen habe?
BlackJack

@Windy: Ich glaube nicht das eine Veränderung als Admin den Beitrag sperrt — nach 5 Minuten wird der automatisch gesperrt. Wir hatten mal jemanden der meinte Diskussionen nachträglich verändern zu müssen und Spammer nerven auch manchmal in dem sie erst harmlose Beiträge erstellen und die dann wenn keiner mehr hinschaut nach einiger Zeit den Text mit Werbelinks ersetzen.

Wenn Dir das mit der `mainloop()` noch nie aufgefallen ist, hast Du so ein Programm wohl noch nie ausserhalb einer IDE aufgerufen die das irgendwie im Hintergrund für Dich löst. :-)

Die direkte Platzierung funktioniert nicht wirklich weil die Leute sehr unterschiedliche Bildschirmgrössen und -auflösungen und dementsprechend auch Pixelgrössen und Schriftgrössen und so weiter haben. Das was bei Dir richtig aussieht, kann bei jemand anderen so ungünstig ineinander Verschoben angezeigt werden, das die GUI nicht mehr richtig bedienbar ist. Und es ist auch massiv arbeitsaufwändig bei einer GUI nachträglich etwas einzufügen, zu entfernen, oder in der Grösse zu verändern oder zu verschieben, wenn man dann von Hand alles mögliche andere was dadurch dann auch verschoben werden muss, anpassen muss. Und zu guter letzt möchte man vielleicht auch mal programmatisch Inhalte ändern die Grössenänderungen nach sich ziehen. Zum Beispiel ein Programm mehrsprachig machen, wodurch sich dann die länge von Texten und damit auch die Grösse von `Button`\s, `Label`\s, usw. ändern.
Windy
User
Beiträge: 8
Registriert: Montag 17. Juli 2017, 11:45

Hi,

wie gesagt ich teste bzw. experimentier etwas mit tkinter herum. Da kommt noch kein PRG zum weitergeben raus. Deswegen ist mir das mit den Klammern auch nicht aufgefallen. Darf ich dich nochmals bemühen, kannst Du sie nachträglich ins Skript reinpacken(die fehlenden Klammern). Ich kann es ja nicht mehr.

Danke nochmals

Viele Grüße
Windy
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Windy hat geschrieben: a = Button(fenster, text='a', command=functools.partial(ereignis, '1'))
a.place(x=10, y= 10)
Ja warum machst Du es nicht so?

Code: Alles auswählen

a = Button(fenster, text='a')
a['command'] = functools.partial(ereignis, '1',a)
a.place(x=10, y= 10)
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Alfons Mittelmeyer hat geschrieben:Ja warum machst Du es nicht so?

Code: Alles auswählen

a = Button(fenster, text='a')
a['command'] = functools.partial(ereignis, '1',a)
a.place(x=10, y= 10)
Ohne dies jetzt getestet zu haben: Es sieht weder einfacher noch intuitiv aus. Und vor allem: wo ist das dokumentiert?
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

kbr hat geschrieben:
Alfons Mittelmeyer hat geschrieben:Ja warum machst Du es nicht so?

Code: Alles auswählen

a = Button(fenster, text='a')
a['command'] = functools.partial(ereignis, '1',a)
a.place(x=10, y= 10)
Ohne dies jetzt getestet zu haben: Es sieht weder einfacher noch intuitiv aus. Und vor allem: wo ist das dokumentiert?
Was soll wo dokumentiert sein? Es is klar, dass man zuerst den Button haben muss, also 'a =', bevor man den Button als Parameter übergeben kann. Oder ist Dir das nicht klar?

Und es ist überall dokumentiert, das man config Parameter auf drei Arten übergeben kann, nämlich beim Anlegen des Widgets:

a = Button(fenster, text='a', command=some_command)

Nachher durch config:
a = Button(fenster)
a.config(text='a', command=some_command)

Nachher so:
a = Button(fenster)
a['text' ] = 'a'
a['command'] = some_command
Zuletzt geändert von Alfons Mittelmeyer am Samstag 29. Juli 2017, 15:06, insgesamt 1-mal geändert.
BlackJack

@kbr: Das ist der Weg den man nehmen muss wenn man das `Button`-Objekt selbst beim Erstellen des Wertes für die Option `command` braucht. Denn beim erstellen des `Button`-Objekts gibt es das ja noch nicht. Ich sehe da jetzt nichts undokumentiertes‽
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@kbr: Das ist der Weg den man nehmen muss wenn man das `Button`-Objekt selbst beim Erstellen des Wertes für die Option `command` braucht. Denn beim erstellen des `Button`-Objekts gibt es das ja noch nicht. Ich sehe da jetzt nichts undokumentiertes‽
Natürlich sind die Arten der Übergabe von config Parametern dokumentiert. Die Frage ist, ist auch dokumentiert, welche Parameter man beim Anlegen des Widgets übergeben kann und welche man erst hinterher dorch config übergeben muss. Ich hatte nämlich gemerkt, dass es Parameter gibt, welche beim Anlegen des Widgets einen Fehler auslösen, aber hinterher bei config funktionieren, Genauso kann es aber bei manchen Parametern auch umgekehrt sein. Leider erinnere ich mich jetzt gerade nicht mehr, welche Parameter das waren.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

BlackJack hat geschrieben:Das ist der Weg den man nehmen muss wenn man das `Button`-Objekt selbst beim Erstellen des Wertes für die Option `command` braucht.
Schon klar. Mich hatte auf die Schnelle das a['command'] irritiert. Aber ja, das geht auch so – das hatte ich wohl vergessen. Ein schneller Blick in tkinter sources zeigte mir jedoch nicht, an welcher Stelle im Code dafür gesorgt wird, dass ein Widget sich wie ein Dictionary verhält. Bei dem tkinter-Code lässt sich aber auch schnell was übersehen.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

kbr hat geschrieben:Ein schneller Blick in tkinter sources zeigte mir jedoch nicht, an welcher Stelle im Code dafür gesorgt wird, dass ein Widget sich wie ein Dictionary verhält. Bei dem tkinter-Code lässt sich aber auch schnell was übersehen.
Ja statt Sourcen, sollte man sich wohl besser zuerst einmal eine Einführung anschauen, etwa: effbot.org/tkinterbook/tkinter-widget-configuration.htm
BlackJack

@kbr: Das steckt in der Klasse `Misc`. Von der erbt `BaseWidget` und von der wiederum `Widget`. Und der Quelltext von dem Modul ist streckenweise nicht schön. :-)
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

BlackJack hat geschrieben:@kbr: Das steckt in der Klasse `Misc`. Von der erbt `BaseWidget` und von der wiederum `Widget`. Und der Quelltext von dem Modul ist streckenweise nicht schön. :-)
Ja, bis 'Misc' war ich gekommen, habe es dort aber nicht gesehen. Und den Quelltext fand ich auch nicht sehr prickelnd ... :)
BlackJack

@kbr: Ich hatte mir mit ``??`` in IPython den Quelltext vom Modul anzeigen lassen und da dann nach ``__setitem__`` gesucht. Unter Linux wird ``less`` zum Anzeigen verwendet und das hat ja eine Suchfunktion. Der erste Treffer war dann auch schon der richtige. Von dort hatte ich rückwärts nach ``^class`` gesucht. :-)
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@BlackJack: IPython ist schon recht praktisch für so was. Zumeist nutze ich es mit Jupyter. Im konkreten Fall habe ich meinen Editor verwendet, der für Editoren über eine gute Suche verfügt. Nach __setitem__ hatte ich gestern nicht gesucht. Dies habe jetzt nachgeholt — und voila, da ist es :)
Antworten