Tkinter messagebox Probleme

Fragen zu Tkinter.
Antworten
Countdown2004
User
Beiträge: 4
Registriert: Mittwoch 5. Februar 2020, 00:30

Guten Tag,

ich bin eine ziemlicher Anfänger was Python angeht und bin auf ein für mich unlösbares Problem gestoßen. Ich versuche gerade ein kleines Programm zu schreiben das, das Werfen eines Würfels simulieren soll. Dafür benutze ich das Random Modul von Python und gebe das Ergebnis mit einer messagebox von tkinter aus. Nun wollte ich aber noch die Option einbauen, dass man auswählen kann ob man einen oder zwei Würfel werfen will. Dafür nahm ich die tkinter Radiobutton Funktion, um eine Option auswählen zu können. Dann definierte ich eine Funktion die abfragen soll welche Option ausgewählt ist, und dann per if-Abfrage eine messagebox mit einem oder zwei Ergebnissen ausgeben soll. Aber wenn ich jetzt versuche diese Funktion auszuführen, passiert nichts. Ich vermute das etwas mit der If-Abfrage nicht stimmt, da alles was in der If-Abfrage passieren sollte nicht ausgeführt wird, aber alles außerhalb der Abfrage schon. Da ich aber nicht selbst drauf komme wäre meine Frage: Was mache ich falsch?

Mein Code:

Code: Alles auswählen

import tkinter as tk
from tkinter import messagebox
import random

ROOT = tk.Tk()
ROOT.title("Dice")
ROOT.geometry("380x25")


#


def closing():
    ROOT.destroy()


# Radiobutton
VAR = tk.StringVar()
R_2 = tk.Radiobutton(text="2 Würfel", variable=VAR, value=2)
R_2.pack(side=tk.RIGHT)
R_1 = tk.Radiobutton(text="1 Würfel", variable=VAR, value=1)
R_1.pack(side=tk.RIGHT)


def abfrage():
    if VAR.get() == 1:
        print("hello")
        r = random.randint(1, 6)
        tk.messagebox.showinfo("Ergebnis", r)
    elif VAR.get() == 2:
        r_1 = random.randint(1, 6)
        r_2 = random.randint(1, 6)
        tk.messagebox.showinfo("Ergebnis", [r_1, r_2])


# buttons


B_1 = tk.Button(text="Würfel werfen", command=abfrage)
B_1.pack(side=tk.LEFT)
B_2 = tk.Button(text="Programm beenden", width=30, command=exit)
B_2.pack(side=tk.BOTTOM)

#


ROOT.mainloop()
Ich hoffe ich habe die Frage am richtigen Ort gestellt, da ich ebenfalls neu in diesem Forum bin, und bedanke mich für alle Antworten im Voraus.
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Countdown2004: Eine Zeichenkette, mit egal welchem Wert, ist halt niemals gleich einer ganze Zahle, egal mit welchem Wert.

Code: Alles auswählen

In [7]: "1" == 1                                                                
Out[7]: False
Davon abgesehen würde man das auch nicht mit einem ``if``/``else`` machen sondern eher mit einer Schleife.

Und das ist ja nett das Du versuchst deinen Editor oder Deine IDE zufrieden zu stellen in dem Du allen Variablen auf Modulebene Namen verpasst die KOMPLETT_GROSS geschrieben und mindestens drei Zeichen lang sind, aber a) gehören auf Modulebene nur Konstanten, denn die werden KOMPLETT_GROSS geschrieben, und b) ist ein Name `B_1` genau so besch…den wie `b1`. Namen sollen dem Leser vermitteln was der Wert dahinter bedeutet. Also keine Abkürzungen und keine durchnummerierten Namen, und nichts *zu* generisches.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Countdown2004: Wenn man `messagebox` importiert sollte man es auch so benutzen und nicht über das `tkinter`-Modul referenzieren.

`closing()` wird nirgends verwendet. Sollte es wohl aber denn `exit()` ist a) nicht dokumentiert, das müsste man explizit aus dem `sys`-Modul importieren, ist b) aber auch viel zu ”hart”. Man will da nicht einfach das Programm hart abwürgen, sondern einfach nur die GUI-Hauptschleife beenden.

Innerhalb eines Containerwidgets sollte man bei `pack()` nicht die Seiten vermischen. Das Ergebnis davon ist schwer vorhersagbar. Und die Breite von einem Button sollte man auch nicht einfach so beschränken, weil dann der Text da nicht mehr rein passen muss. Warum die Fenstergrösse festgelegt wird, ist mir auch nicht so wirklich klar. Bei mir sieht die GUI so aus:
Bild

In `abfrage()` wird nichts abgefragt, der Name ist also falsch, weil irreführend.

Code: Alles auswählen

#!/usr/bin/env python3
import random
import tkinter as tk
from functools import partial
from tkinter import messagebox

MAX_DIE_COUNT = 2


def roll_dice(die_count_var):
    result = [random.randint(1, 6) for _ in range(die_count_var.get())]
    messagebox.showinfo("Ergebnis", result)


def main():
    root = tk.Tk()
    root.title("Dice")

    die_count_var = tk.IntVar(value=1)

    tk.Button(
        text="Würfel werfen", command=partial(roll_dice, die_count_var)
    ).pack(side=tk.LEFT)
    tk.Button(text="Programm beenden", command=root.quit).pack(side=tk.LEFT)
    for i in range(1, MAX_DIE_COUNT + 1):
        tk.Radiobutton(
            text=f"{i} Würfel", variable=die_count_var, value=i
        ).pack(side=tk.LEFT)

    root.mainloop()


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Count
User
Beiträge: 28
Registriert: Donnerstag 28. November 2019, 12:56

moin,
du musst aus

Code: Alles auswählen

VAR = tk.StringVar()
das machen
VAR = tk.IntVar()
und wenn die 2 Würfel zusammen gerechnet werden sollen ,dann "[r_1 + r_2]" statt "[r_1,r_2]"

dann passt alles
Countdown2004
User
Beiträge: 4
Registriert: Mittwoch 5. Februar 2020, 00:30

@Count
Vielen Dank für die Antwort, jetzt funktioniert es. Nur versteh ich nicht so ganz warum ich "[r_1 + r_2]" statt "[r_1,r_2]" schreiben soll. Da ich ja nicht will das die zwei Werte der Würfel zusammen gerechnet werden, sondern einzeln angezeigt werden.


@__blackjack__
Und das ist ja nett das Du versuchst deinen Editor oder Deine IDE zufrieden zu stellen in dem Du allen Variablen auf Modulebene Namen verpasst die KOMPLETT_GROSS geschrieben und mindestens drei Zeichen lang sind, aber a) gehören auf Modulebene nur Konstanten, denn die werden KOMPLETT_GROSS geschrieben, und b) ist ein Name `B_1` genau so besch…den wie `b1`. Namen sollen dem Leser vermitteln was der Wert dahinter bedeutet. Also keine Abkürzungen und keine durchnummerierten Namen, und nichts *zu* generisches.
Es tut mir leid, aber ich kenne den Unterschied zwischen Variablen und Konstanten nicht. Ich benutze Pylint als Linter, um Fehler in meinem Code zu verbessern. Und ja stimmt schon, ich habe meinen Code einfach so abgeändert dass Pylint nichts mehr anzeigt. Da dies nur ein privates Projekt war, habe ich die Namen, wie zum Beispeil "b_1", nicht sehr gut ausgewählt was lesbarkeit angeht. Es ist definitiv etwas was ich mir für die Zukunft angewöhnen sollte besser zu machen, insbesondere wenn ich meinen Code in einem Forum zeige.
`closing()` wird nirgends verwendet. Sollte es wohl aber denn `exit()` ist a) nicht dokumentiert, das müsste man explizit aus dem `sys`-Modul importieren, ist b) aber auch viel zu ”hart”. Man will da nicht einfach das Programm hart abwürgen, sondern einfach nur die GUI-Hauptschleife beenden.
Die Funktion wurde nirgends verwendet, da ich vergessen hab die Funktion des Knopfes zu closing() zu ändern. Ist aber anscheinend sowieso nicht die beste Variante mein Programm zu beenden.
Innerhalb eines Containerwidgets sollte man bei `pack()` nicht die Seiten vermischen. Das Ergebnis davon ist schwer vorhersagbar. Und die Breite von einem Button sollte man auch nicht einfach so beschränken, weil dann der Text da nicht mehr rein passen muss. Warum die Fenstergrösse festgelegt wird, ist mir auch nicht so wirklich klar.
Ich weiß leider nicht was mit Seiten vermischen gemeint ist. Entschuldigung, aber wäre eine genauere erklärung möglich? DIe Breite der Buttons habe ich festgelegt da sie sich nicht automatisch dem Text angepasst haben, und somit der Text auch so abgeschnitten war wie im screenshot gezeigt. Warum ich die Fenstergröße festgelegt habe, weiß ich ehrlich gesagt gerade nicht, da es wenn ich es nun weg lasse perfekt funktioniert. Aber ich meine mich zu erinnern, dass es etwas damit zu tun hatte, dass es sich so automatisch festgelegt hat, dass alles ziemlich zusammen gedrückt aussah. Das könnte aber etwas damit zu tun haben, dass die Anordnung vorher anders war.

Vielen dank für alle Antworten, und bitte entschuldigt, dass ich vielleicht nicht alles auf anhieb verstehe.
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Mit „Seiten“ vermischen ist das `side`-Argument von `pack()` gemeint. Innerhalb eines Containerwidgets sollte man immer nur *einen* Wert für alle ge`pack()`ten Widgets verwenden. Das Ergebnis kann sonst schwer vorhersehbar sein und es kann auch passieren das Widgets andere Widgets verdecken.

Die Breite von Buttons passt sich automatisch dem Inhalt an wenn man *keine* Grösse vorgibt. Wenn man eine Grösse vorgibt, dann passt sich die Grösse natürlich nicht mehr an, denn dann wird die vorgegebene Grösse verwendet.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Countdown2004
User
Beiträge: 4
Registriert: Mittwoch 5. Februar 2020, 00:30

Ok, jetzt habe ich es verstanden.

Vielen Dank für die Antwort.
Count
User
Beiträge: 28
Registriert: Donnerstag 28. November 2019, 12:56

deswegen schrieb ich ja auch "wenn du willst, dass..." ^^

Nur versteh ich nicht so ganz warum ich "[r_1 + r_2]" statt "[r_1,r_2]" schreiben soll. Da ich ja nicht will das die zwei Werte der Würfel zusammen gerechnet werden, sondern einzeln angezeigt werden.
Countdown2004
User
Beiträge: 4
Registriert: Mittwoch 5. Februar 2020, 00:30

Ok, hab mich nur ein wenig gewundert. Aber danke für die Antwort, war eine große Hilfe.
Antworten