Mon code est le suivant:

from tkinter import *
window = Tk()
print("What is 5 times 5?")
optionA = 25
optionB = 10
optionC = 3125
optionD = 55
print("A:", optionA)
print("B:", optionB)
print("C:", optionC)
print("D:", optionD)
def chooseA():
    userAnswer = optionA
def chooseB():
    userAnswer = optionB
def chooseC():
    userAnswer = optionC
def chooseD():
    userAnswer = optionD
window.bind("<Left>", chooseA)
window.bind("<Up>", chooseB)
window.bind("<Down>", chooseC)
window.bind("<Right>", chooseD)
if userAnswer == 25:
    print("You correctly answered the question!")

Mon problème est que j'obtiens une erreur indiquant que userAnswer n'est pas défini. Cela est dû au fait que le code n'a pas de fonction qui attend que l'utilisateur appuie sur l'une des quatre touches fléchées. Quelqu'un a-t-il une suggestion sur la façon de faire attendre le programme pour 1 pression sur 4 touches? Vos réponses sont grandement appréciées! (P.S. L'utilisation de la commande keyboard.wait du module clavier n'attend pas plusieurs touches.)

-1
MakeHellTal 19 mars 2019 à 00:21

2 réponses

Meilleure réponse

Voici une solution, mais peut-être pas la meilleure (il y a probablement des modules juste pour ça, mais j'aime m'entraîner à coder avec des threads quand je peux).

from threading import Thread
from tkinter import *

def check_with_thread(): # make a function our thread can attach to
    global userAnswer
    local_check = userAnswer
    while True:
        if userAnswer != local_check: # user has selected a new value
            if userAnswer == 25:
                print("That's correct!")
                break # have our thread break infinite loop and end it's execution
            else:
                print(userAnswer)
                local_check = userAnswer # Make it able to detect changes in values


window = Tk() # Actually make a window! Why is this not in the OP???
print("What is 5 times 5?")
optionA = 25
optionB = 10
optionC = 3125
optionD = 55
print("A:", optionA)
print("B:", optionB)
print("C:", optionC)
print("D:", optionD)
def chooseA(event):
    global userAnswer # we are modifying the global variable our thread is looking at
    userAnswer = optionA
def chooseB(event):
    global userAnswer
    userAnswer = optionB
def chooseC(event): # the .bind() sends events, so these need a positional argument for them
    global userAnswer
    userAnswer = optionC
def chooseD(event):
    global userAnswer
    userAnswer = optionD
window.bind("<Left>", chooseA)
window.bind("<Up>", chooseB)
window.bind("<Down>", chooseC)
window.bind("<Right>", chooseD)
userAnswer = None
t = Thread(target=check_with_thread) # make a thread to check the input
t.start() # get our thread running before generating the window

window.mainloop()

Comment ça fonctionne

Tout d'abord, nous définissons une fonction à exécuter pour notre thread (les threads sont l'une des méthodes que votre programme est capable de faire littéralement 2 choses à la fois. Ceci est nécessaire car window.mainloop() empêchera notre thread principal de notre script de faire quoi que ce soit autre). Nous spécifions que notre fonction doit lire la variable globale userAnswer avec global userAnswer, sinon elle s'attendrait à ce que cette variable soit locale (définie dans la fonction et oubliée lorsque la fonction se termine à moins qu'elle ne soit renvoyée). Ensuite, nous initialisons la variable locale local_check pour être ce que userAnswer se trouve être lorsque la fonction est appelée. Enfin, nous entrons dans une boucle infinie. Dans cette boucle, nous vérifierons si l'utilisateur a mis à jour sa réponse en la comparant à notre local_check précédemment créé. Si la réponse a été mise à jour, ces valeurs seront différentes ! Nous continuerons à rechercher de nouvelles réponses jusqu'à ce qu'ils sélectionnent la bonne réponse de 25 où nous appellerons break pour mettre fin à notre boucle while (sinon, elle continuerait indéfiniment). À ce stade, nous avons atteint la fin de notre fonction, donc le thread qui lui est assigné mourra lorsqu'il atteindra ce point. Ensuite, nous allons créer userAnswers et lui attribuer une valeur de None afin que lorsque notre thread atteint la ligne local_check = userAnswer, il sache quoi faire et ne rencontre pas d'erreur de nom. Il ne reste plus qu'à faire notre fil. Nous le faisons avec t = Thread(target=check_with_thread), puis le démarrons immédiatement. Le thread est maintenant opérationnel et vérifie les modifications apportées à l'entrée, et nous pouvons enfin démarrer window.mainloop() dans le thread principal de notre script.

Pourquoi utiliser un fil ?

Un thread est utilisé car window.mainloop() bloque. Cela signifie que si nous avons essayé:

# stuff from previous script
window.mainloop()
thing = 5
print(thing)

Nous ne verrons rien imprimé jusqu'à ce que après l'utilisateur ferme notre interface graphique. Cela signifie que nos liaisons ne sont plus en vigueur et ne peuvent pas être utilisées pour modifier ce que l'utilisateur a sélectionné. Grâce à l'utilisation d'un thread, nous sommes en mesure d'avoir deux boucles infinies traitant des informations simultanément, ce qui est une astuce très précieuse à connaître pour les programmeurs (pourquoi je m'entraîne quand je peux)

2
Reedinationer 18 mars 2019 à 22:48

Essayez d'ajouter:

window = tkinter.Tk()

En haut de votre code, et

window.mainloop()

À la fin. Cela créera une fenêtre qui restera ouverte jusqu'à ce que vous la fermiez manuellement.

0
Granny Aching 18 mars 2019 à 21:30