Ошибка типа Tkinter: аргумент типа ‘StringVar’ не может быть повторен

#python #user-interface #tkinter

#python #пользовательский интерфейс #tkinter

Вопрос:

Я пытаюсь написать графический интерфейс, который эмулирует игру Hangman, используя Tkinter. До сих пор я получил графический интерфейс для создания метки, которая обновляется на основе букв, которые пользователь угадал правильно, но терминал по-прежнему выдает ошибку: «TypeError: аргумент типа’StringVar’ не является итеративным». Я рассмотрел другие решения этой ошибки, но не смог понять, как решить проблему.

Это еще не сделано, но пока что это код:

 import randomword
# from PyDictionary import PyDictionary
from tkinter import *

root = Tk()

playerWord: str = randomword.get_random_word()
word_guess: str = ''
guesses = ''


def returnEntry(arg=None):
    global word_guess
    global guesses
    global wordLabel
    word_guess = ''
    # dictionary = PyDictionary()

    failed = 0
    incorrect = 10
    result = myEntry.get()

    while incorrect > 0:
        if not result.isalpha():
            resultLabel.config(text="that's not a letter")

        elif len(result) != 1:
            resultLabel.config(text="that's not a letter")

        else:
            resultLabel.config(text=result)
            assert isinstance(END, object)
            myEntry.delete(0, END)

        guesses  = result

        for char in playerWord:
            if char in guesses:
                # Print the letter they guessed
                word_guess  = char

            elif char not in guesses:
                # Print "_" for every letter they haven't guessed
                word_guess  = "_ "
                failed  = 1

        if guesses[len(guesses) - 1] not in playerWord:
            resultLabel.config(text="wrong")
            incorrect -= 1

        wordLabel = Label(root, updateLabel(word_guess))
        myEntry.delete(0, END)


resultLabel = Label(root, text="")
resultLabel.pack(fill=X)


myEntry = Entry(root, width=20)
myEntry.focus()
myEntry.bind("<Return>", returnEntry)
myEntry.pack()


text = StringVar()
text.set("your word is: "   ("_ " * len(playerWord)))
wordLabel = Label(root, textvariable=text)
wordLabel.pack()


def updateLabel(word):
    text.set("your word is: "   word)
    return text


mainloop()
  

проблема возникает, когда я запускаю функцию для wordLabel: «wordLabel = Label(root, updateLabel (word_guess))» для сброса метки. Любые предложения о том, как я могу обновить метку до word_guess после итерации цикла while?

Комментарии:

1. Можете ли вы включить обратную трассировку python, чтобы мы могли видеть полный текст ошибки плюс строку с ошибкой?

Ответ №1:

Эта строка вызывает ошибку:

 wordLabel = Label(root, updateLabel(word_guess))
  

Вы переоценили это. Это должно быть просто так:

 updateLabel(word_guess)
  

У вас также есть еще одна серьезная ошибка. Эта строка:

 while incorrect > 0:
  

Приведет к блокировке вашей программы. Вам нужно изменить его на это:

 if incorrect > 0:
  

Ответ №2:

 wordLabel = Label(root, updateLabel(word_guess))
  

Вы пытаетесь создать новый Label и сделать глобальную wordLabel ссылку на новую метку вместо старой. Даже если бы он работал правильно, это не привело бы к обновлению вашего графического интерфейса, поскольку новая метка не упакована.

Причина, по которой он прерывается, заключается в том, что, хотя updateLabel он изменяет содержимое StringVar имени text и возвращает его обратно, он не используется в качестве textvariable новой метки. Помимо указания родительского виджета, вы должны использовать только аргументы ключевого слова для конструктора, иначе аргумент, вероятно, будет интерпретироваться иначе, чем вы ожидаете. (Честно говоря, я удивлен, что вы вообще можете вызывать функцию таким образом; я бы ожидал a TypeError в момент вызова.)

В любом случае, все, что вам нужно сделать, поскольку text оно также является глобальным, — это напрямую .set преобразовать его в новый текст. Это автоматически обновит внешний вид wordLabel (по модулю любого материала tkinter, необходимого для обновления отображения в целом) — в этом смысл класса контейнера StringVar (в отличие от простого использования простой строки).