Fenster schließen

Fragen zu Tkinter.
Antworten
deather4
User
Beiträge: 8
Registriert: Freitag 1. Juni 2012, 15:14

Hallo,
ich bin recht neu in der python programmierung.
Zurzeit machen wir python in der Schule seit etwa einenm halben Jahr.
Nun sollen wir ein Spiel programmieren.
Wir haben uns Wer wird Millionär ausgesucht.
Aber wir haben ein Problem:
Wir haben Fragen mit 4 Antworten, eine ist richtig und öffnet eine neue Definition
bei der sich ein neues Fenster mit einer Frage und Antworten öffet.
Nur wie kann man das Fenster zuvor wieder schließen ohne es manuell zu tun

Code: Alles auswählen

from Tkinter import *
from random import *


def Frage50():
    f50=Tk()
    a="In welcher deutschen Stadt wurde der Reichstag verhüllt?"
    b="Welches Tier hat das Baden Württenberg im Wappen?"

    

    if randint(1,2)==1:
          

        L1=Label(f50,text=a)
        L1.pack(side='top')
        
        b1=Button(f50,text='A:Bonn',command=f50.destroy)
        b1.pack(side='top')
    
        b2=Button(f50,text='B:Berlin  ',command=Frage100)
        b2.pack(side='top')

        b3=Button(f50,text='C:Hamburg',command=f50.destroy)
        b3.pack(side='top')

        b4=Button(f50,text='D:München',command=f50.destroy)
        b4.pack(side='top')

    else:
        L2=Label(f50,text=b)
        L1.pack(side='top')
        
        b5=Button(f50,text='A:Adler',command=f50.destroy)
        b5.pack(side='top')
    
        b6=Button(f50,text='B:Fisch  ',command=f50.destroy)
        b6.pack(side='top')

        b7=Button(f50,text='C:Bär',command=f50.destroy)
        b7.pack(side='top')

        b8=Button(f50,text='D:Löwe',command=Frage100)
        b8.pack(side='top')

    
    f50.geometry('300x150-700+350')
    f50.mainloop()




def Frage100():
    f100=Tk()
    c="Was gilt als König der Tiere ?"
    d="Welches Tier rollt sich bei Gefahr zu einer Kugel?"

    if randint(1,2)==1:

        L3=Label(f100,text=c)
        L3.pack(side='top')

        b9=Button(f100,text='A:',command=f100.destroy)
        b9.pack(side='top')
    
        b10=Button(f100,text='B:Katze  ',command=Frage500)
        b10.pack(side='top')

        b11=Button(f100,text='C:Schwein',command=f100.destroy)
        b11.pack(side='top')

        b12=Button(f100,text='D:Igel',command=f100.destroy)
        b12.pack(side='top')
    else:
        L4=Label(f100,text=d)
        L4.pack(side='top')

        b13=Button(f100,text='A:Pferd',command=f100.destroy)
        b13.pack(side='top')
    
        b14=Button(f100,text='B:Katze  ',command=frage500)
        b14.pack(side='top')

        b15=Button(f100,text='C:Schwein',command=f100.destroy)
        b15.pack(side='top')

        b16=Button(f100,text='D:Igel',command=f100.destroy)
        b16.pack(side='top')

        f100.geometry('300x150-700+350')
        f100.mainloop()






menue=Tk()
mb2=Button(menue,text='Verlassen',command=menue.destroy)
mb2.pack(side='bottom')

mb=Button(menue,text='Spielen',command=Frage50)
mb.pack(side='bottom')

menue.geometry('300x150-700+350')
menue.mainloop()

PS:Das sind jetzt nur zwei Fragen, später werden es noch mehr bis zur 1Mio Frage halt :D
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi deather4

Hier etwas zum herumspielen:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import Tkinter as tk
from random import randint, choice
from functools import partial

QUESTIONS = {
    1: {
        "Question": "In welcher deutschen Stadt wurde der Reichstag verhüllt?",
        "Answers": [
                ['A:', 'Bonn', False], 
                ['B:', 'Berlin', True],
                ['C:', 'Hamburg', False],
                ['D:', 'München', False]]},
                
    2: {
        "Question": "Welches Tier hat das Baden Württenberg im Wappen?",
        "Answers": [
                ['A:', 'Adler', False], 
                ['B:', 'Fisch', False],
                ['C:', 'Bär', False],
                ['D:', 'Löwe', True]]},
                
    3: {
        "Question": "Was gilt als König der Tiere ?",
        "Answers": [
                ['A:', 'Vogel', False], 
                ['B:', 'Löwe', True],
                ['C:', 'Katze', False],
                ['D:', 'Schwein', False]]},
                
    4: {
        "Question": "Welches Tier rollt sich bei Gefahr zu einer Kugel?",
        "Answers": [
                ['A:', 'Pferd', False], 
                ['B:', 'Katze', False],
                ['C:', 'Igel', True],
                ['D:', 'Affe', False]]},
            }

class QuestionDialog(tk.Toplevel):
    
    def __init__(self, key, callback=None):

        tk.Toplevel.__init__(self)
        self.title('Frage-{0}'.format(key))
        
        
        question = QUESTIONS[key]["Question"]
        
        frame = tk.Frame(self)
        frame.pack(padx=10, pady=10)
        
        tk.Label(frame, text=question, font=('Helvetica', 14, 'bold'),
            fg='red').pack(padx=10, pady=5)
        
        [tk.Button(frame, text=nr+answer, command=partial(callback, check, self)
            ).pack(fill='x', padx=20, pady=2)
                for nr, answer, check in QUESTIONS[key]["Answers"]]


def ask_question(check=None, dialog=None):
    
    if check is None:
        QuestionDialog(choice(QUESTIONS.keys()), ask_question)
        return
    
    dialog.destroy()
        
    if check:
        QuestionDialog(choice(QUESTIONS.keys()), ask_question)
    
    
app_win=tk.Tk()
app_win.title("Wer wird Millionär")

tk.Button(app_win,text='Spielen',command=ask_question).pack(expand=True)
tk.Button(app_win,text='Verlassen',command=app_win.destroy).pack(expand=True)

app_win.geometry('250x80-700+350')
app_win.mainloop()
Jetzt aber sofort hinter die Bücher!

Gruß wuf :wink:
Take it easy Mates!
deather4
User
Beiträge: 8
Registriert: Freitag 1. Juni 2012, 15:14

Danke erstmal:)
nur das problem ist. Das wir classs noch nicht durchgenommen
haben und wir sollten ja später wissen was in dem programm
steht

mfg deather
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi deather4

Es geht natürlich auch ohne Klasse:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import Tkinter as tk
from random import randint, choice
from functools import partial

QUESTIONS = {
    1: {
        "Question": "In welcher deutschen Stadt wurde der Reichstag verhüllt?",
        "Answers": [
                ['A:', 'Bonn', False], 
                ['B:', 'Berlin', True],
                ['C:', 'Hamburg', False],
                ['D:', 'München', False]]},
                
    2: {
        "Question": "Welches Tier hat das Baden Württenberg im Wappen?",
        "Answers": [
                ['A:', 'Adler', False], 
                ['B:', 'Fisch', False],
                ['C:', 'Bär', False],
                ['D:', 'Löwe', True]]},
                
    3: {
        "Question": "Was gilt als König der Tiere ?",
        "Answers": [
                ['A:', 'Vogel', False], 
                ['B:', 'Löwe', True],
                ['C:', 'Katze', False],
                ['D:', 'Schwein', False]]},
                
    4: {
        "Question": "Welches Tier rollt sich bei Gefahr zu einer Kugel?",
        "Answers": [
                ['A:', 'Pferd', False], 
                ['B:', 'Katze', False],
                ['C:', 'Igel', True],
                ['D:', 'Affe', False]]},
            }

def create_dialog(key, callback):
    
    dialog_win = tk.Toplevel()
    dialog_win.title('Frage-{0}'.format(key))
    
    
    question = QUESTIONS[key]["Question"]
    
    frame = tk.Frame(dialog_win)
    frame.pack(padx=10, pady=10)
    
    tk.Label(frame, text=question, font=('Helvetica', 14, 'bold'),
        fg='red').pack(padx=10, pady=5)
    
    [tk.Button(frame, text=nr+answer, command=partial(callback, check,
        dialog_win)).pack(fill='x', padx=20, pady=2)
            for nr, answer, check in QUESTIONS[key]["Answers"]]    

def ask_question(check=None, dialog=None):
    
    if check is None:
        create_dialog(choice(QUESTIONS.keys()), ask_question)
        return
    
    dialog.destroy()
        
    if check:
        create_dialog(choice(QUESTIONS.keys()), ask_question)
    
    
app_win=tk.Tk()
app_win.title("Wer wird Millionär")

tk.Button(app_win,text='Spielen',command=ask_question).pack(expand=True)
tk.Button(app_win,text='Verlassen',command=app_win.destroy).pack(expand=True)

app_win.geometry('250x80-700+350')
app_win.mainloop()
Gruß wuf :wink:
Take it easy Mates!
deather4
User
Beiträge: 8
Registriert: Freitag 1. Juni 2012, 15:14

Das ist ja alles schön und gut,
aber nicht die antwort auf meine frage,
ich werde mich mit dem programm beschäftiegen,
brauche jetzt aber erstmal eine lösung für mein problem,
da wir ein bisscchen unter zeitdruck stehen.

mfg deather

PS: das soll jetzt kein vorwurf sein, nur wir haben halt keine
zeit etwas neues auszuprobieren. :(
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

OK deather4

Dein Skript enthält einige Fehler!!!

Das folgende darf nur einmal für das Hauptfenster verwendet werden: Für weitere Fenster mit den Fragen muss folgendes Widget verwendet werden:

Code: Alles auswählen

Toplevel()
Diese können wieder entfernt werden mit:

Code: Alles auswählen

Toplevel.destroy()
Dein modifiziertes Skript (Würde ich nie so schreiben):

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

from Tkinter import *
from random import *


def Frage50():
    #f50=Tk()
    f50 = Toplevel()
    a="In welcher deutschen Stadt wurde der Reichstag verhüllt?"
    b="Welches Tier hat das Baden Württenberg im Wappen?"

   

    if randint(1,2)==1:
         

        L1=Label(f50,text=a)
        L1.pack(side='top')
       
        b1=Button(f50,text='A:Bonn',command=f50.destroy)
        b1.pack(side='top')
   
        #b2=Button(f50,text='B:Berlin  ',command=Frage100)
        b2=Button(f50,text='B:Berlin  ',command=lambda :richtig_50(f50))
        b2.pack(side='top')

        b3=Button(f50,text='C:Hamburg',command=f50.destroy)
        b3.pack(side='top')

        b4=Button(f50,text='D:München',command=f50.destroy)
        b4.pack(side='top')

    else:
        L2=Label(f50,text=b)
        #L1.pack(side='top')
        L2.pack(side='top')
       
        b5=Button(f50,text='A:Adler',command=f50.destroy)
        b5.pack(side='top')
   
        b6=Button(f50,text='B:Fisch  ',command=f50.destroy)
        b6.pack(side='top')

        b7=Button(f50,text='C:Bär',command=f50.destroy)
        b7.pack(side='top')

        #b8=Button(f50,text='D:Löwe',command=Frage100)
        b8=Button(f50,text='D:Löwe',command=lambda :richtig_50(f50))
        b8.pack(side='top')

   
    f50.geometry('300x150-700+350')
    f50.mainloop()

def richtig_50(f50):
        
    f50.destroy()
    Frage100()

def Frage100():
    #f100=Tk()
    f100 = Toplevel()
    c="Was gilt als König der Tiere ?"
    d="Welches Tier rollt sich bei Gefahr zu einer Kugel?"

    if randint(1,2)==1:

        L3=Label(f100,text=c)
        L3.pack(side='top')

        #b9=Button(f100,text='A:',command=f100.destroy)
        b9=Button(f100,text='A:Tier fehlt!',command=f100.destroy)
        b9.pack(side='top')
   
        #b10=Button(f100,text='B:Katze  ',command=Frage500)
        #b10=Button(f100,text='B:Katze  ',command=Frage50)
        b10=Button(f100,text='B:Katze  ',command=lambda :richtig_100(f100))
        b10.pack(side='top')

        b11=Button(f100,text='C:Schwein',command=f100.destroy)
        b11.pack(side='top')

        b12=Button(f100,text='D:Igel',command=f100.destroy)
        b12.pack(side='top')
    else:
        L4=Label(f100,text=d)
        L4.pack(side='top')

        b13=Button(f100,text='A:Pferd',command=f100.destroy)
        b13.pack(side='top')
   
        #b14=Button(f100,text='B:Katze  ',command=frage500)
        #b14=Button(f100,text='B:Katze  ',command=Frage50)
        b14=Button(f100,text='B:Katze  ',command=lambda :richtig_100(f100))
        b14.pack(side='top')

        b15=Button(f100,text='C:Schwein',command=f100.destroy)
        b15.pack(side='top')

        b16=Button(f100,text='D:Igel',command=f100.destroy)
        b16.pack(side='top')

        f100.geometry('300x150-700+350')
        f100.mainloop()

def richtig_100(f100):
        
    f100.destroy()
    Frage50()





menue=Tk()
mb2=Button(menue,text='Verlassen',command=menue.destroy)
mb2.pack(side='bottom')

mb=Button(menue,text='Spielen',command=Frage50)
mb.pack(side='bottom')

menue.geometry('300x150-700+350')
menue.mainloop()
Wünsche dir noch viel Spass und Zeit beim erlernen von Python & Tkinter

Gruß wuf :wink:
Take it easy Mates!
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Mehr Hilfe als die von wuf kann man nun wirklich nicht verlangen, das ist eine (eigentlich ja sogar zwei) sehr gute Vorlage, wie das Spiel sinnvoll umsetzbar ist. Ihr werdet mehr Zeit sparen, wenn ihr wufs Ansatz versteht, als wenn ihr versucht euren zu korrigieren. Was ihr geschrieben habt hat nicht viel mit Programmieren zu tun und wird euch bei neuen Fragen oder winzigen Anpassungen im Interface über den Kopf wachsen. Zum Programmieren gehört immer abstrahieren und das Erkennen von Gemeinsamkeiten. Wenn ihr tausend Fragen schreibt und entschließt, dass die Buttons nun verschiedene Farben haben sollen, dann müsst die an tausend Fragen Änderungen durchnehmen. Bei wufs Ansatz reich genau eine Änderung für beliebig viele Fragen.

Ich kann mich noch an eine Gruppe in meinem Informatikunterricht in der Schule erinnern (der nun tatsächlich schon 10 Jahre her ist), welche eine ähnliche Aufgabe so umgesetzt hat. Dort wurde eine recht große for-Schleife mittels copy&paste umgesetzt. Die Aufgabe wurde damals nicht als gelöst anerkannt, da dieses Vorgehen nichts mit Programmieren zu tun hat.
Das Leben ist wie ein Tennisball.
deather4
User
Beiträge: 8
Registriert: Freitag 1. Juni 2012, 15:14

@Wuf Danke diesen befehl kannte ich bis jetzt noch nicht,

@EyDu verlang nicht so viel von uns.Wir machen seit 3 unterrichtsstunden GUI(Tkinter). Außerdem sind wir erst in der 9.
Was für ein Lösungsweg hättest du denn. Zu dem ersten vorschlag von Wuf wir hatten das Modul functools noch nicht.
Wie gesagt wir haben seit 3 Unterrichtstunden Tkinter.

Mfg deather
BlackJack

@deather4: Das `functools`-Modul hat nichts direkt mit GUIs zu tun sondern mit Funktionen. Was `partial()` macht kann man in der Dokumentation nachlesen.

Und der andere grosse Kritikpunkt, das „Programmieren” durch wiederholtes kopieren von einem Quelltextabschnitt als Vorlage und dort dann Daten austauschen ist wirklich wichtig. Das ist ebenfalls unabhängig von GUIs. Das DRY-Prinzip (Don't Repeat Yourself) und wie man es in verschiedenen Situationen umsetzen kann, muss ein Programmierer/Entwickler drauf haben. Normalerweise bevor er mit GUIs anfängt.

Am Anfang steht eigentlich immer die Frage welche Daten man hat, welche Operationen man darauf ausführen will, und welche Kodierungen und Datenstrukturen für Daten und Operationen sich am besten eignen. Und dabei sollte in der Regel nicht heraus kommen, dass man pro Datensatz eine Funktion schreibt (oder kopiert), die vom Syntaxbaum her immer gleich ist.

Manchmal fängt man auch mit einem GUI-Prototyp an. Das dient dann aber dazu besser zu verstehen wie ein Benutzer das Programm verwenden wird und welche Daten er dazu wann braucht, welche Operationen er dazu ausführt, und welche Operationen dafür in der Programmlogik vorhanden sein müssen. Was einen dann wieder zu den Überlegungen aus dem vorherigen Absatz bringt.
deather4
User
Beiträge: 8
Registriert: Freitag 1. Juni 2012, 15:14

import Tkinter as tk
from random import randint, choice
from functools import partial

QUESTIONS = {
1: {
"Question": "In welcher deutschen Stadt wurde der Reichstag verhüllt?",
"Answers": [
['A:', 'Bonn', False],
['B:', 'Berlin', True],
['C:', 'Hamburg', False],
['D:', 'München', False]]},

2: {
"Question": "Welches Tier hat das Baden Württenberg im Wappen?",
"Answers": [
['A:', 'Adler', False],
['B:', 'Fisch', False],
['C:', 'Bär', False],
['D:', 'Löwe', True]]},

3: {
"Question": "Was gilt als König der Tiere ?",
"Answers": [
['A:', 'Vogel', False],
['B:', 'Löwe', True],
['C:', 'Katze', False],
['D:', 'Schwein', False]]},

4: {
"Question": "Welches Tier rollt sich bei Gefahr zu einer Kugel?",
"Answers": [
['A:', 'Pferd', False],
['B:', 'Katze', False],
['C:', 'Igel', True],
['D:', 'Affe', False]]},
}

def create_dialog(key, callback):

dialog_win = tk.Toplevel()
dialog_win.title('Frage-{0}'.format(key))


question = QUESTIONS[key]["Question"]

frame = tk.Frame(dialog_win)
frame.pack(padx=10, pady=10)

tk.Label(frame, text=question, font=('Helvetica', 14, 'bold'),
fg='red').pack(padx=10, pady=5)

[tk.Button(frame, text=nr+answer, command=partial(callback, check,
dialog_win)).pack(fill='x', padx=20, pady=2)
for nr, answer, check in QUESTIONS[key]["Answers"]]

def ask_question(check=None, dialog=None):

if check is None:
create_dialog(choice(QUESTIONS.keys()), ask_question)
return

dialog.destroy()

if check:
create_dialog(choice(QUESTIONS.keys()), ask_question)


app_win=tk.Tk()
app_win.title("Wer wird Millionär")

tk.Button(app_win,text='Spielen',command=ask_question).pack(expand=True)
tk.Button(app_win,text='Verlassen',command=app_win.destroy).pack(expand=True)

app_win.geometry('250x80-700+350')
app_win.mainloop()
Könnte man das auch so mache, das die Fragen nacheinader kommen also von 1-4 und nicht durch zufall.
Wenn ja könntet ihr mir das zeigen, mit erklärung bitte.

Mfg dether4

PS: @Blackjack du hattes recht, suche gerade nach einer anderen lösung
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Natürlich, du musst dir nur merken, welche Frage du vorher hattest. Für dich wäre es am einfachsten, wenn du dir einfach den Index speicherst.

Das Dictionary mit den Fragen solltest du übrigens durch eine Liste ersetzen. Das Durchnummerierne von Schlüsseln ist ein deutlicher Hinweis, dass man die falsche Datenstruktur gewählt hat.

Edit: Und setze deinen Code doch bitte in PYTHON-Codetags, dann geht nicht die Einrückung verloren. Ohne diese, wird sich niemand dein Programm anschauen wollen.
Das Leben ist wie ein Tennisball.
deather4
User
Beiträge: 8
Registriert: Freitag 1. Juni 2012, 15:14

@ eydu
kannst du mir das mal zeigen, ich hab nur ein bisschen verstanden,
mit dem code wolte ich dich eigentlich deinen code zitieren

Mfg deather4
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Da stellt sich natürlich die Frage, in welcher Zeile des von dir zitierten Codes die Frage zufällig ausgewählt wird. Nicht, dass ich es nicht wüsste, die Frage ist nur, ob du es auch verstanden hast. Wenn du die Zeile gefunden hast, dann überlegst du dir am besten genau was dort passiert und probierst die ensprechende Zeile im Interpreter aus. Dann änderst du das Programm vielleicht einfach mal so, dass immer die erste Frage ausgewählt wird. Wenn du das hinbekommen hast, dann sollte dir auch klar sein, was du dir speichern musst um zur nächsten Frage zu kommen.
Das Leben ist wie ein Tennisball.
deather4
User
Beiträge: 8
Registriert: Freitag 1. Juni 2012, 15:14

Code: Alles auswählen

def ask_question(check=None, dialog=None):
   
    if check is None:
        create_dialog(choice(QUESTIONS.keys()), ask_question)
        return
   
    dialog.destroy()
       
    if check:
        create_dialog(choice(QUESTIONS.keys()), ask_question)
in crate_dialog(choice.....)
steht das, aber ich hab immer noch nicht verstanden was ich jetzt tun soll damit
Zuletzt geändert von deather4 am Donnerstag 21. Juni 2012, 14:16, insgesamt 1-mal geändert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@deather4: Du musst Deinen Code wohl noch mal editieren, da die Einrückungen verloren gegangen sind! Zudem benutze bitte die Python-Code-Tags, wie von EyDu schon angesprochen: [ code=python ]... [ /code ] (ohne die Leerzeichen!)

Ich habe zu Demozwecken auch mal ein solches kleines Quiz geschrieben, Code findest Du hier. Daran könntest Du sehen, dass Du Deine Datenstruktur noch verbessern könntest; sowohl die Buchstaben als auch die Infos `True` oder `False` zu jeder Antwort sind eigentlich nicht explizit notwendig, da man sie sich aus der Struktur herleiten kann - zumindest bei der Konvention, die richtige Antwort immer als erstes stehen zu haben ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten