Как преобразовать алфавитный ввод в wx.TextCtrl во все заглавные буквы?

Я пытаюсь написать свой первый валидатор для wx.TextCtrl на основе этот ответ на другой вопрос на SO, который должен делать следующее:

Все буквы должны быть напечатаны заглавными, а текстовое поле должно содержать только заглавные буквы и цифры.

Однако мои попытки терпят неудачу в двух отношениях:

  • Когда я изменяю свой шаблон (взятый из связанного ответа), в текстовое поле ничего не добавляется.

  • Я не могу заменить маленькие буквы на заглавные.

Вот моя попытка:

import wx
import string

########################################################################
class CharValidator(wx.PyValidator):
    ''' Validates data as it is entered into the text controls. '''

    #----------------------------------------------------------------------
    def __init__(self, flag):
        wx.PyValidator.__init__(self)
        self.flag = flag
        self.Bind(wx.EVT_CHAR, self.OnChar)

    #----------------------------------------------------------------------
    def Clone(self):
        '''Required Validator method'''
        return CharValidator(self.flag)

    #----------------------------------------------------------------------
    def Validate(self, win):
        return True

    #----------------------------------------------------------------------
    def TransferToWindow(self):
        return True

    #----------------------------------------------------------------------
    def TransferFromWindow(self):
        return True

    #----------------------------------------------------------------------
    def OnChar(self, event):
        keycode = int(event.GetKeyCode())
        if keycode < 256:
            if keycode > 96 & keycode < 123:
                keycode = keycode - 32
            #print keycode
            key = chr(keycode)
            #print key
            return
        event.Skip()

########################################################################
class ValidationDemo(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, wx.ID_ANY, 
                          "Text Validation Tutorial")

        panel = wx.Panel(self)
        textOne = wx.TextCtrl(panel, validator=CharValidator('no-alpha'))

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(textOne, 0, wx.ALL, 5)
        panel.SetSizer(sizer)

# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = ValidationDemo()
    frame.Show()
    app.MainLoop()

person Henrik    schedule 08.04.2012    source источник


Ответы (2)


В вашем демонстрационном фрейме есть проблема со структурой дерева виджетов wxPython. Это позволит вам написать в текстовом элементе управления:

class ValidationDemo(wx.Frame):
    """"""
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, wx.ID_ANY, 
                          "Text Validation Tutorial")

        textOne = wx.TextCtrl(self, validator=CharValidator('no-alpha'))

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(textOne, 1, wx.ALL| wx.EXPAND, 5)
        self.SetSizer(sizer)
        self.Fit()

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

Это работает (объясняю в комментариях):

def OnChar(self, event):
    keycode = int(event.GetKeyCode())
    #
    # get the widget where the text entry takes place
    object = self.GetWindow()
    #
    # for upper-case and for numbers, let the event go
    if (58 > keycode > 47) or ( 91 > keycode > 64):
        event.Skip()
    #
    # for lower-case, convert to upper and write it yourself
    elif 123 > keycode > 96:
        keycode = keycode - 32
        key = chr(keycode)
        object.write(key)

Примечание. Я вызываю self.GetWindow() для каждого события char. В вашем случае, имея только один элемент управления с помощью валидатора, вы можете определить self.object только один раз при инициализации валидатора.

person joaquin    schedule 08.04.2012
comment
Спасибо за ваш ответ. В конце концов я понял, что я не функция валидатора, а обработчик событий, как вы, кажется, тоже подразумеваете. Смотрите мой собственный ответ, который реализует это. - person Henrik; 12.04.2012

На самом деле весь бардак с функцией валидации излишен. Вам просто нужен обработчик событий (обратите внимание, что он написан неаккуратно и жестко закодирован для конкретного объекта textOne вместо того, чтобы принимать входной объект).

Кроме того, кажется хорошей идвой переместить InsertionPoint:

import wx

class ValidationDemo(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, wx.ID_ANY, 
                          "Text Validation Tutorial")

        panel = wx.Panel(self)
        self.textOne = wx.TextCtrl(panel)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.textOne, 0, wx.ALL, 5)
        panel.SetSizer(sizer)

        self.Bind(wx.EVT_TEXT, self.OnTextType, self.textOne)

    def OnTextType(self, event):
        self.textOne.ChangeValue(unicode.upper(self.textOne.GetValue()))
        self.textOne.SetInsertionPointEnd()


# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = ValidationDemo()
    frame.Show()
    app.MainLoop()
person Henrik    schedule 12.04.2012
comment
Вы должны выбрать ответ, который отвечает на ваш опубликованный вопрос и требования, а не на ваши собственные запоздалые размышления. В любом случае ваш ответ не отвечает вашим собственным опубликованным требованиям: во-первых, он ничего не проверяет, просто преобразует в верхний регистр все, что можно преобразовать, а во-вторых, он не соответствует выделенной вами строке, текстовое поле должно содержать только заглавные буквы и цифры . Поэтому я предлагаю вам автоматически поставить минус :-). - person joaquin; 12.04.2012
comment
Возможно, мой вопрос был неправильно сформулирован. Мне действительно не нужен валидатор. Я просто хочу, чтобы все буквы были заглавными. И вы правы, отбрасывание не цифр или символов не реализовано. Однако именно этого я и хотел добиться. По крайней мере, он отвечает на буквальный вопрос (например, заголовок). Я не хочу показаться грубым и очень ценю ваш ответ. Но это ответ, который я нашел, и я опубликовал его и принял в качестве ссылки (и не заработал за это никаких баллов). Нормально для тебя? - person Henrik; 12.04.2012