Ограничение значения в виджете Tkinter Entry - PullRequest
8 голосов
/ 22 января 2012

Мне нужно ограничить значения в виджете ввода только числами. Способ, который я реализовал:

import numpy as np
from Tkinter import *;
import tkMessageBox;

class window2:

    def __init__(self,master1):

        self.panel2=Frame(master1)
        self.panel2.grid()

        self.button2=Button(self.panel2,text="Quit",command=self.panel2.quit)
        self.button2.grid()

        self.text1=Entry(self.panel2)
        self.text1.grid()
        self.text1.bind('<KeyPress>', self.keybind1)
        self.text1.focus()

    def keybind1 (self,event):
        if event.int in np.linspace(0,9,10):
            print event.int


root1=Tk()
window2(root1)
root1.mainloop()

Я получаю сообщение об ошибке, что у экземпляра Event нет атрибута int. Что я должен делать?

Ответы [ 6 ]

15 голосов
/ 22 января 2012

Используется validatecommand для ограничения допустимого пользовательского ввода в tk.Entry строками, которые можно интерпретировать как числа с плавающей запятой:

import tkinter as tk

class window2:
    def __init__(self, master1):
        self.panel2 = tk.Frame(master1)
        self.panel2.grid()
        self.button2 = tk.Button(self.panel2, text = "Quit", command = self.panel2.quit)
        self.button2.grid()
        vcmd = (master1.register(self.validate),
                '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
        self.text1 = tk.Entry(self.panel2, validate = 'key', validatecommand = vcmd)
        self.text1.grid()
        self.text1.focus()

    def validate(self, action, index, value_if_allowed,
                       prior_value, text, validation_type, trigger_type, widget_name):
        if value_if_allowed:
            try:
                float(value_if_allowed)
                return True
            except ValueError:
                return False
        else:
            return False

root1 = tk.Tk()
window2(root1)
root1.mainloop()

Ссылки:

  • Tk man page объясняет опции validate и validatecommand.(Спасибо schlenk за ссылку).
  • Я научился делать это в Python здесь .
7 голосов
/ 10 октября 2017

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

Используйте функцию проверки, которая поставляется с виджетом Entry.

Предположим, self это виджет:

vcmd = (self.register(self.callback))

w = Entry(self, validate='all', validatecommand=(vcmd, '%P')) 
w.pack()

def callback(self, P):
    if str.isdigit(P) or P == "":
        return True
    else:
        return False

Вам не нужно включать все коды замены : ('%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W'), необходимы только те, которые вы будете использовать.

Виджет Entry возвращает строку, поэтому вам придется каким-то образом извлекать любые цифры, чтобы отделить их от других символов. Самый простой способ сделать это - использовать str.isdigit(). Это удобный небольшой инструмент, встроенный прямо в библиотеки Python и не требующий дополнительного импорта, и он будет идентифицировать любые цифры (цифры), которые он найдет из строки , которую возвращает виджет Entry.

Часть or P == "" оператора if позволяет вам удалить всю вашу запись, без нее вы не сможете удалить последнюю (первую в поле ввода) цифру из-за '%P', возвращающего пустое значение и вызывающего Ваш обратный вызов для возврата False. Я не буду вдаваться в подробности, почему здесь.

validate='all' позволяет обратному вызову оценивать значение P при focusin, focusout или при любом key изменении содержимого виджета и, следовательно, вы не оставляете никаких отверстий для отклонения. ошибочно введенные символы.

В общем, чтобы все было просто. Если ваш обратный вызов вернет True, это позволит ввести данные. Если обратный вызов возвращает «False», он по существу «игнорирует» ввод с клавиатуры.

Проверьте эти две ссылки. Они объясняют, что означает каждый код замещения и как их реализовать.

http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/entry-validation.html http://stupidpythonideas.blogspot.ca/2013/12/tkinter-validation.html

EDIT: Это будет заботиться только о том, что разрешено в коробке. Однако внутри обратного вызова вы можете добавить любое значение, которое P имеет к любой переменной, которую вы хотите.

5 голосов
/ 25 июня 2015

Ответ почти идеален, просто небольшое дополнение, позволяющее удалить всю строку.Проверка на наличие поплавков должна выполняться только при вставке текста

def validate_float(self, action, index, value_if_allowed,
    prior_value, text, validation_type, trigger_type, widget_name):
    # action=1 -> insert
    if(action=='1'):
        if text in '0123456789.-+':
            try:
                float(value_if_allowed)
                return True
            except ValueError:
                return False
        else:
            return False
    else:
        return True
1 голос
/ 16 июня 2016

Мне также пришлось иметь дело с начальной вставкой. Вот чем я закончил:

    def _checkNumberOnly(self, action, value_if_allowed):
        if action != '1':
           return True
        try:
            return value_if_allowed.isnumeric()
        except ValueError:
           return False

    vcmd = (self.register(self._checkNumberOnly), '%d', '%P')
        self.port = ttk.Entry(self, width=35, validate='key', validatecommand=vcmd)

Следовательно, он действителен для:

    self.port.insert(0, '6379')

Я не уверен, что catch необходим, поскольку isnumeric() не указывает, что возникает исключение.

0 голосов
/ 03 июня 2019

, если вы имеете дело с локалями, в которых запятая является десятичной точкой:

locale.setlocale(locale.LC_ALL,'de_DE.UTF-8') # German

vcmd = (self.root.register(self.entry_numericonly), '%d', '%P')

self.my_float_entry = tk.Entry(self.root, ... , validate='key', validatecommand=vcmd)

def entry_numericonly(self, action, value_if_allowed):
    if(action == "1"):
        try:
            loc_float  = locale.atof(value_if_allowed)
            loc_float_format = locale.format("%f", loc_float)
            try:
                loc_same_length = loc_float_format[:len(value_if_allowed)]
                return value_if_allowed == loc_same_length
            except:
                return False                    
        except:
            return False
    else:
        return True
0 голосов
/ 26 августа 2017

Я новичок в Python и Tkinker, но это лучше всего работает для меня:

    def keybind1 (self,event):
        v = event.char
        try:
            v = int(v)
        except ValueError:
            if v!="\x08" and v!="":
            return "break"

v = int(v) вызывает ValueError на любой клавише, кроме цифровых клавиш, и операторы if v!="\x08 и v!="":" все еще позволяют клавишам backspace, ("\x08") и delete, стрелкам, home, end и т. д. (которые имеют event.char из "") работать нормально. Команда break останавливает ввод нежелательного символа в поле ввода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...