Hallo zusammen!
Ich habe ein kleines Programm geschrieben um das Scale-Widget unter tkinter auszuprobieren. Im Widget wird der (Benzin-)Verbrauch eingestellt, danach wird die Reichweite mit einer Tankfüllung berechnet. Klappt soweit, aber ...
def reichweite(self):
try:
stand = float(txtStand.get())
verbrauch = scwert.get()
rweite = stand*100/verbrauch
lb2["text"] = f"{rweite:8.2f}"
except:
lb2["text"] = "error"
rufe ich "reichweite()" vom Scale-Widget aus, wird verlangt die Funktion einen Parameter
rufe ich dieselbe Funktion mit einem Button auf, wird der Parameter als Fehler angezeigt.
Wie kann ich erreichen, das "Reichweite()" von beiden Widgets aus gestartet werden kann?
Vielen Dank für Eure Hilfe
Frage zu Parametern bei CallBack
Erster Schritt wäre, das nackte `except` wegzulöschen und den tatsächlichen Fehler sich anzusehen.
Dann brauchen wir auch den kompletten Code und den wirklichen Fehler, um da was sagen zu können.
Es ist komisch, dass `reichweite` ein self-Argument hat, das aber gar nicht benutzt.
Dann brauchen wir auch den kompletten Code und den wirklichen Fehler, um da was sagen zu können.
Es ist komisch, dass `reichweite` ein self-Argument hat, das aber gar nicht benutzt.
Das abfangen von allen Fehlern mit einem allumfassenden try/except ist ein Problem, denn damit verschleierst du dir ganz schnell echte Programmierfehler, statt erwartete Fehler abzufangen. Darum immer die spezifischen erwarteten Ausnahmen angeben.
Wenn dich der Parameter ansonsten nicht interessiert, kannst du mit
einfach alle zusaetzlichen Argumente abfangen. Und ignorieren. Was der einzelne Unterstrich fuer den werten Leser des Codes klarmacht per Konvention.
Wenn dich der Parameter ansonsten nicht interessiert, kannst du mit
Code: Alles auswählen
def reichweite(self, *_args):
...
- __blackjack__
- User
- Beiträge: 14092
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Wobei da nur ein Argument übergeben wird wenn das als Rückruf vom `scale()` verwendet wird: der aktuelle Wert.
“It is easier to change the specification to fit the program than vice versa.” — Alan J. Perlis
Vielen Dank!
hat geholfen.
Vielleicht könnt Ihr mir noch ein wenig theoretischen Background geben. Ich habe mich ja selbst auch über das "self" als Parameter gewundert, dass ja nirgendwo verwendet wird. Ich habe das ganze aus einem Python-Buch übernommen.
Dort wird bei einer Callback Funktion, die durch ein Button ausgelöst wird, auf Parameter verzichtet also, dagegen beim Auslösen durch ein Scale-Widget mit self gearbeitet.
Beides für sich funktioniert. Kann mir jemand den Unterschied erklären?
Code: Alles auswählen
def reichweite(*_args):
Vielleicht könnt Ihr mir noch ein wenig theoretischen Background geben. Ich habe mich ja selbst auch über das "self" als Parameter gewundert, dass ja nirgendwo verwendet wird. Ich habe das ganze aus einem Python-Buch übernommen.
Dort wird bei einer Callback Funktion, die durch ein Button ausgelöst wird, auf Parameter verzichtet also
Code: Alles auswählen
def reichweite()
Code: Alles auswählen
def reichweite(self)
Da wirst Du wohl recht haben. Erklärst Du es bitte besser?Sirius3 hat geschrieben: Donnerstag 20. Februar 2020, 20:56 Das zeigt, dass der Autor keine Ahnung von Python- und GUI-Programmierung hat und das didaktisch auch nicht gut rüberbringen kann.
Wie __blackjack__ schon geschrieben hat, ist der eine Parameter, der dem Callback übergeben wird, die Position. Diese Position `self` zu nennen ist quatsch, sollte besser `position` heißen.
Ein Callback für einen Knopf hat keinen Parameter, weil außer Klick keine Information damit verbunden ist.
Auch anderen Variablennamen im Beispiel sind sehr schlecht gewählt, weil sie Abkürzungen sind, die man vermeiden sollte, weil sie einem nur das Lesen und Verstehen erschweren.
Ein Callback für einen Knopf hat keinen Parameter, weil außer Klick keine Information damit verbunden ist.
Auch anderen Variablennamen im Beispiel sind sehr schlecht gewählt, weil sie Abkürzungen sind, die man vermeiden sollte, weil sie einem nur das Lesen und Verstehen erschweren.
- __blackjack__
- User
- Beiträge: 14092
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Eigentlich sollte die Signatur so aussehen:
Allerdings mit vernünftigen Namen, ohne kryptische Abkürzungen, und in der Schreibweise den Konventionen bei Python entsprechend (Style Guide for Python Code).
Und `txtStand`, `scwert`, und `lb2` wären nicht auf Modulebene definiert, sondern in einer Funktion oder Methode. Und man würde `functools.partial()` verwenden um die Rückruffunktion zu erstellen, die diese Werte gebunden hat.
Oder man hätte doch ein `self` als erstes Argument wenn man das als Methode in einer Klasse definiert, wo man letztlich bei jeder nicht-trivialen GUI sowieso nicht drum herum kommt.
Code: Alles auswählen
def reichweite(txtStand, scwert, lb2, *_args):
...
Und `txtStand`, `scwert`, und `lb2` wären nicht auf Modulebene definiert, sondern in einer Funktion oder Methode. Und man würde `functools.partial()` verwenden um die Rückruffunktion zu erstellen, die diese Werte gebunden hat.
Oder man hätte doch ein `self` als erstes Argument wenn man das als Methode in einer Klasse definiert, wo man letztlich bei jeder nicht-trivialen GUI sowieso nicht drum herum kommt.
“It is easier to change the specification to fit the program than vice versa.” — Alan J. Perlis
Erstmal Danke für die Hinweise.
Also in etwa
Da ich Python-Anfänger bin, war mein Beispiel tatsächlich eher trivial. Aber verstehe ich Deine Aussage richtig, dass man bei nicht-trivialen GUI-Anwendungen eine Klasse für das Hauptformular erzeugt und dann eine Instanz davon?__blackjack__ hat geschrieben: Freitag 21. Februar 2020, 09:32 Oder man hätte doch ein `self` als erstes Argument wenn man das als Methode in einer Klasse definiert, wo man letztlich bei jeder nicht-trivialen GUI sowieso nicht drum herum kommt.
Also in etwa
Code: Alles auswählen
class mainform:
def __init__(self,...)
...
main =mainform( ...)
- __blackjack__
- User
- Beiträge: 14092
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@PhilM: Das ist IMHO schon an der Grenze von nicht-trivial weil an diese Funktion zwei Callbacks gebunden werden und man bei beiden eine Zwischenfunktion erstellen muss bei denen drei Widgets für den Aufruf gebunden werden.
Zum Codeschnippsel – in etwa. Aber wie gesagt: Es gibt Konventionen. Die Klasse würde eher `MainForm` heissen. Eingerückt wird mit vier Leerzeichen pro Ebene, also nicht wie im Beispiel mit Tabulatorzeichen.
Zum Codeschnippsel – in etwa. Aber wie gesagt: Es gibt Konventionen. Die Klasse würde eher `MainForm` heissen. Eingerückt wird mit vier Leerzeichen pro Ebene, also nicht wie im Beispiel mit Tabulatorzeichen.
“It is easier to change the specification to fit the program than vice versa.” — Alan J. Perlis