При проверке введенного символа в поле, происходит бесконечное зацикливание
я новичок в написании кода, но появилось дикое желание разобраться как оно все работает. Попробовал написать простейшую игрушку, всем известную города, голый код работает коректно. Но голый код -это не красиво( Попробовал создать графическое оформление, для этого использовал библиотеку Tkinter.. Во время проверки введеного символа(что бы начать игру, нужно ввести первую букву, для первого города) Использовал файл, с символами, заранее написанными. Если вводить символы из данного файла, то проверка проходит успешно, но если не символов нет в данном файле, происходит бесконечный цикл. Подозреваю то, что поле ввода, не очищается автоматический, хотя я прописал это.(когда символ совпадает с символами из фалами, то поле нормально очищается.) помогите пожалуйста..
def btn_click():
global pervayaBukva
global с
global С
global gorod
global pole
def proverkaNaZnakiIprobel():
global pervayaBukva
global gorod
global c
global C
global pole
# В Simbol.txt содержатся все символы кириллицы, строчные.
with open('Simbol.txt') as file:
for i in file:
c.append(i.strip())
print(c)
#Если на вход подается символ кириллицы, все нормально.
while C != 1:
if pervayaBukva in c:
C += 1
#Если латиница, в коде ниже происходит бесконечный цикл..
elif pervayaBukva not in c:
pole.delete(0, tk.END)
print('dsd')
gorod.config(text='Введите одну букву')
pervayaBukva = pole
pole.delete(0, tk.END)
return (pervayaBukva)
pervayaBukva=pole.get()
#строка ниже, не исполняется, если в переменной pervayaBukva введены символы которых нет в тхт файле.
pole.delete(0, tk.END)
print(pervayaBukva)
proverkaNaZnakiIprobel()
#тело графического оформления
pervayaBukva=str()
VvodGoroda = str()
proverka = int()
ispGoroda = list()
lastBukva = str()
Povtor = 1
K = 0
z = 0
c = list()
C = 0
infa=str()
window = tk.Tk()
window.resizable(width=False, height=False)
window.wm_attributes('-alpha', 0.6)
window.geometry('640x480')
privet=tk.Label(text='Добро пожаловать в игру: города', width=1, height=1)
privet.place(relheight=0.2,relwidth=1)
gorod=tk.Label(text='Введите любую букву:')
gorod.place(relx=0.2, rely=0.15,relheight=0.1,relwidth=0.5)
pole=tk.Entry()
pole.place(relx=0.35,rely=0.25,relheight=0.1,relwidth=0.3)
knoka=tk.Button(text='Нажми сюда, что бы ввести город',command=btn_click)
knoka.place(relx=0.32,rely=0.4,relheight=0.1,relwidth=0.35)
window.mainloop()
Ответы (1 шт):
Смотрите, вот ваш цикл:
while C != 1:
if pervayaBukva in c:
C += 1
#Если латиница, в коде ниже происходит бесконечный цикл..
elif pervayaBukva not in c:
pole.delete(0, tk.END)
print('dsd')
gorod.config(text='Введите одну букву')
pervayaBukva = pole
pole.delete(0, tk.END)
Допустим, пользователь ввел букву из кириллицы, нажал кнопку, из файла буквы загрузились (предположим, что там только буквы кириллицы).
При входе в цикл C = 0, проверяется, что первая буква в списке букв, условие if pervayaBukva in c: выполняется, C увеличивается на 1 и становится равным 1, на следующей итерации выходим из цикла.
Теперь, допустим, пользователь ввел латинскую букву. Тогда срабатывает вторая ветка условия (elif pervayaBukva not in c:), C не увеличивается (остается равным 0), в pervayaBukva записывается само текстовое поле (а не его содержимое), цикл повторяется опять, опять входим во вторую ветку (т.к. текстовое поле не является буквой кириллицы или буквой вообще), и т.д. до бесконечности.
Даже если исправить получение текста из текстового поля, пользователь на этот цикл не может повлиять, т.к. бесконечный цикл блокирует работу графического интерфейса. Логично вообще убрать цикл, работать будет примерно так как вы задумали.
Тут лучше считывать набор букв один раз в самом начале программы (у вас они считываются каждый раз заново при каждом нажатии на кнопку, и список постоянно удлиняется), и вообще блокировать любые нажатия кроме нажатия на буквы, прочитанные из файла, для этого в обработчике нажатия на кнопку внутри текстового поля нужно возвращать строку "break":
import tkinter as tk
window = tk.Tk()
gorod=tk.Label(text='Введите любую букву:')
gorod.pack()
c = list()
with open('Simbol.txt') as file:
for i in file:
c.append(i.strip())
# print(c)
def on_key_press(event: tk.Event):
# print(event)
if event.keysym == "BackSpace":
return None # Не блокируем BackSpace
if event.char not in c:
return "break" # Блокируем ввод всего кроме букв считанных из файла
if len(pole.get()) >= 1:
return "break" # Блокируем ввод, если уже что-то введено (текстовое поле не пустое)
pole=tk.Entry()
pole.pack()
pole.bind("<KeyPress>", on_key_press)
window.mainloop()
Еще мысли:
- для ввода одной буквы (или по одной букве) не обязательно иметь целое текстовое поле, достаточно обработки нажатий клавиш и вывода введенных букв в
Label; - называйте переменные так, чтобы было понятно, для чего они нужны, не используйте однобуквенные имена переменных;
- уж точно не нужно называть две переменные одной и той же буквой в разном регистре (
Cиc); - с помощью
globalнужно обозначать только те переменные, значения которых вы хотите перезаписать: текстовое поле или метку вы не заменяете новым текстовым полем или меткой, а просто меняете значение в существующих объектах, поэтомуglobalдля них не нужно.