É possível limitar TextCtrl para aceitar somente números em wxPython?
Pergunta
Eu quero ter um controle de texto que aceita apenas números.(Apenas valores inteiros, como 45 ou 366)
Qual é a melhor maneira de fazer isso?
Solução
IntCtrl
, Masked Edit Control
, e NumCtrl
são todos projetados para fazer exatamente isso, com diferentes níveis de controle. Confira a demonstração do WX em "mais Windows/Controls" para ver como eles funcionam.
(Ou, se você está realmente ansioso para fazer isso diretamente com um texto bruto, acho que você gostaria de pegar eventos EVT_CHAR, testar os personagens e ligar para Evt.skip () se fosse um caractere permitido.)
Outras dicas
Eu tive que fazer algo semelhante, verificando códigos alfanuméricos. A dica em EVT_Char foi a coisa certa:
class TestPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, -1)
self.entry = wx.TextCtrl(self, -1)
self.entry.Bind(wx.EVT_CHAR, self.handle_keypress)
def handle_keypress(self, event):
keycode = event.GetKeyCode()
if keycode < 255:
# valid ASCII
if chr(keycode).isalnum():
# Valid alphanumeric character
event.Skip()
Você pode tentar IntCtrl
, EVT_CHAR
, ou a implementação de uma nova ou existente avaliador (como IntValidator).Validadores pode ser usado para validar um campo (útil quando está a tentar validar várias coisas em uma caixa de diálogo do painel/) e eles também podem ser usados com EVT_CHAR para restringir a entrada em um campo.
Como observam outras respostas, é possível fazer isso com um EVT_CHAR
manipulador. Você vai querer ligar event.Skip()
Para os personagens que você deseja deixar, e não chamá -lo para aqueles que você deseja bloquear. Uma nuance é que você provavelmente também quer ligar event.Skip()
para caracteres de guia; Pressionar a guia desencadeia o EVT_CHAR
evento, e se você não ligar event.Skip()
, você desativará efetivamente a travessia da guia entre TextCtrl
s.
Aqui está um aplicativo mínimo mostrando dois TextCtrl
s que aceitam números inteiros ou decimais, com a travessia da guia de trabalho:
import wx
app = wx.App()
frame = wx.Frame(None, -1, 'simple.py')
panel = wx.Panel(frame)
text_ctrl_1 = wx.TextCtrl(panel, value='123')
text_ctrl_2 = wx.TextCtrl(panel, value='456', pos=(0, 30))
def block_non_numbers(event):
key_code = event.GetKeyCode()
# Allow ASCII numerics
if ord('0') <= key_code <= ord('9'):
event.Skip()
return
# Allow decimal points
if key_code == ord('.'):
event.Skip()
return
# Allow tabs, for tab navigation between TextCtrls
if key_code == ord('\t'):
event.Skip()
return
# Block everything else
return
text_ctrl_1.Bind(wx.EVT_CHAR, block_non_numbers)
text_ctrl_2.Bind(wx.EVT_CHAR, block_non_numbers)
frame.Show()
app.MainLoop()
Numctrl tem algumas peculiaridades estranhas para mim. Aqui está minha tentativa de criar um controle numérico com base em EVT_Char e KeyCode.
Esse controle permite números, bem como todo o código de chave especial (combo ctrl, chave de seta, backspace etc ...), de modo que a cola de cópia, o desfazer-Redo, a seleção-tudo etc. ainda funcione. Ele apenas bloqueará outros caracteres imprimíveis (usando String.printable) e caracteres unicode (usando Wxk_none)
Outra maneira de verificar e permitir que todo o código de chave especial possa ser encontrado por esta resposta. Esta é uma abordagem melhor, mas requer mais código.
import string
MyNumCtrl = wx.TextCtrl()
MyNumCtrl.Bind(EVT_CHAR, onChar)
def onChar(self, event):
keycode = event.GetKeyCode()
obj = event.GetEventObject()
val = obj.GetValue()
# filter unicode characters
if keycode == wx.WXK_NONE:
pass
# allow digits
elif chr(keycode) in string.digits:
event.Skip()
# allow special, non-printable keycodes
elif chr(keycode) not in string.printable:
event.Skip() # allow all other special keycode
# allow '-' for negative numbers
elif chr(keycode) == '-':
if val[0] == '-':
obj.SetValue(val[1:])
else:
obj.SetValue('-' + val)
# allow '.' for float numbers
elif chr(keycode) == '.' and '.' not in val:
event.Skip()
return
Por favor, verifique o script "validator.py" na demonstração do WXPYTHON. É exatamente o que você precisa