Как проверить входные виджеты в Python Tkinter - PullRequest
0 голосов
/ 03 сентября 2018

Я сейчас работаю над базовой программой калькулятора. Я пытаюсь использовать функцию проверки, чтобы пользователь мог вводить только значения из списка valild_input. Функция test_input, содержащая этот список, работает нормально, пока я не решу набрать "=" или нажать equals button. Когда я нажимаю equals_button, текущее уравнение в записи display не удаляется и заменяется результатом. Хотя этого не происходит, когда я нажимаю клавишу «=» на клавиатуре. Единственная проблема заключается в том, что знак равенства остается на display, и после этого виджет ввода вообще прекращает проверять введенные пользователем данные.

from tkinter import *
from tkinter import messagebox

def replace_text(text):
    display.delete(0, END)
    display.insert(0, text)

#Calculates the input in the display        
def calculate(event = None):
    equation = display.get()
    try:
        result = eval(equation)
        replace_text(result)
    except: 
        messagebox.showerror("Error", "Math Error", parent = root)

def test_input(value, action):
    valid_input = ["7", "8", "9", "+", "4", "5", "6", "-", "1", "2", "3", "*", "0", ".", "/"]
    if action == "1":
        if value not in valid_input:
            return False
        return True

root = Tk() 
root.title("Calculator testing")

display = Entry(root, font=("Helvetica", 16), justify = "right", validate = "key")
display.configure(validatecommand = (display.register(test_input), "%S", "%d"))
display.insert(0, "")
display.grid(column = 0, row = 0, columnspan = 4, sticky = "NSWE", padx = 10, pady = 10)
display.bind("=", calculate)

#Equals button
button_equal = Button(root, font = ("Helvetica", 14), text = "=", command = 
calculate, bg = "#c0ded9")
button_equal.grid(column = 2, row = 1, columnspan = 2, sticky = "WE")

#All clear button 
button_clear = Button(root, font = ("Helvetica", 14), text = "AC", command = lambda: replace_text(""), bg = "#c0ded9")
button_clear.grid(column = 0, row = 1, columnspan = 2, sticky = "WE")

#Main Program       
root.mainloop()

1 Ответ

0 голосов
/ 03 сентября 2018

Есть 2 проблемы с вашим кодом.

  1. Функция проверки всегда должна возвращать логическое значение.

    С этот ответ :

    Важно, чтобы команда проверки вернула либо True, либо False. Все остальное приведет к отключению проверки для виджета.

    Ваша test_input функция этого не делает - есть ветка, в которой она возвращает None.

    def test_input(value, action):
        valid_input = ["7", "8", "9", "+", "4", "5", "6", "-", "1", "2", "3", "*", "0", ".", "/"]
        if action == "1":
            if value not in valid_input:
                return False
            return True
        # None is being returned here!
    

    Именно поэтому проверка отключена после того, как ваша программа удаляет текст из записи. Исправить это просто: вернуть True вместо None.

    def test_input(value, action):
        valid_input = ["7", "8", "9", "+", "4", "5", "6", "-", "1", "2", "3", "*", "0", ".", "/"]
        if action == "1":
            if value not in valid_input:
                return False
            return True
    
        # if action != 1, allow it
        return True
    
  2. Функция проверки должна обрабатывать многосимвольный ввод.

    Вы предположили, что функция проверки вызывается для каждого введенного символа. Это верно, когда пользователь вводит формулу с помощью клавиатуры, но не при копировании / вставке или установке текста записи с помощью .insert(...). Ваша функция должна обрабатывать эти случаи.

    def test_input(value, action):
        valid_input = ["7", "8", "9", "+", "4", "5", "6", "-", "1", "2", "3", "*", "0", ".", "/"]
        if action == "1":
            return all(char in valid_input for char in value)
    
        # if action != 1, allow it
        return True
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...