문제

I want to have a text control that only accepts numbers. (Just integer values like 45 or 366)

What is the best way to do this?

도움이 되었습니까?

해결책

IntCtrl, Masked Edit Control, and NumCtrl are all designed to do just this, with different levels of control. Checkout the wx demo under "More Windows/Controls" to see how they work.

(Or, if you're instead really looking forward to doing this directly with a raw TextCtrl, I think you'd want to catch EVT_CHAR events, test the characters, and call evt.Skip() if it was an allowed character.)

다른 팁

I had to do something similar, checking for alphanumeric codes. The tip on EVT_CHAR was the right thing:

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()

You can try IntCtrl, EVT_CHAR, or implement a new/existing validator (like IntValidator). Validators can be used to validate a field (useful when trying to validate multiple things on a dialog/panel) and they can also be used with EVT_CHAR to restrict input in a field.

As other answers note, it's possible to do this with an EVT_CHAR handler. You'll want to call event.Skip() for the characters you want to let through, and not call it for the ones you want to block. One nuance is that you probably also want to call event.Skip() for tab characters; pressing tab triggers the EVT_CHAR event, and if you don't call event.Skip(), you'll effectively disable tab traversal between TextCtrls.

Here's a minimal application showing two TextCtrls that accept integer or decimal numbers, with working tab traversal:

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 has some weird quirks to me. Here is my attempt to create a Number control based on EVT_CHAR and keycode.

This control allow numbers as well as all special keycode (ctrl combo, arrow key, backspace etc...), so that copy-paste, undo-redo, select-all etc still works. It will only block other printable characters (using string.printable) and unicode characters (using WXK_NONE)

Another way to check and allow all special keycode can be found by this answer. This is a better approach but requires more code.

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

Please check "Validator.py" script in wxpython demo. it is exactly what you need

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top