jlt199
jlt199

Reputation: 2449

wxpython call a function when focus of TextCtrl changes

Morning, I would like to call a function in my GUI in the event that the content of a TextCtrl is changed. Only after the user leaves the TextCtrl object though, not during editing.

Please can you help me find the right event handler to use, I'm very new to wxpython and I can't even find a list of allowable events.

Many thanks

Upvotes: 0

Views: 919

Answers (2)

I_4m_Z3r0
I_4m_Z3r0

Reputation: 1090

I did a listener that bind the keyboard events and set the input only to be a numerical value on the TxtCtrl, you can change this listener to the behaviour you prefer (:

Usage:

self.__MyTxtCtrl.Bind(wx.EVT_CHAR, self.__on_change_text_check_is_int_value)


def __on_change_text_check_is_float_value(self, evt):
        KeyboardEventUtils.on_change_text_check_is_int_value(self, evt)

This is the listener in a singleton utils class:

from pyglet.window import key
from Utils.NumberUtils import NumberUtils

ENTRY_ID = "id"
ENTRY_KEY_EVENT = "keyEvent"
ENTRY_SELECTION_EVENT = "selectionEvent"

MASK_STARTED_RIGHT_SELECTION = 1
MASK_STARTED_LEFT_SELECTION = -1

class KeyboardEventUtils(object):

    __mLastEvt = {}

    def on_change_text_check_is_float_value(self, evt):
        txt = evt.GetEventObject()
        strng = txt.GetValue()
        rawKey = evt.GetRawKeyCode()
        modifiers = evt.GetModifiers()

        if KeyboardEventUtils.__mLastEvt != None and len(KeyboardEventUtils.__mLastEvt) > 0 and KeyboardEventUtils.__mLastEvt[ENTRY_ID] != txt.GetId():
            self._mLastEvt = {}

        if chr(rawKey).isnumeric() or (rawKey == key.PERIOD and not chr(rawKey) in strng and len(strng) > 0) or (rawKey == key.MINUS and not chr(rawKey) in strng and (len(strng) == 0 or txt.GetInsertionPoint() == 0)):
            pos = txt.GetInsertionPoint()
            txt.SetValue(str(float(txt.GetValue()[:pos] + chr(rawKey) + txt.GetValue()[pos:])))
            txt.SetInsertionPoint(pos + 1)

        elif (modifiers == 4 or modifiers == key.MOD_SHIFT) and rawKey == key.LEFT:             # 4 (?) key.MOD_SHIFT (?)
            pos = txt.GetInsertionPoint()
            rng = list(txt.GetSelection())

            if rng[0] == rng[1] and ENTRY_SELECTION_EVENT in KeyboardEventUtils.__mLastEvt:
                del KeyboardEventUtils.__mLastEvt[ENTRY_SELECTION_EVENT]

            if ENTRY_SELECTION_EVENT in KeyboardEventUtils.__mLastEvt and KeyboardEventUtils.__mLastEvt[ENTRY_SELECTION_EVENT] == MASK_STARTED_RIGHT_SELECTION:

                rng[1] = rng[1] - 1
            else:
                KeyboardEventUtils.__mLastEvt[ENTRY_SELECTION_EVENT] = MASK_STARTED_LEFT_SELECTION
                rng[0] = rng[0] - 1

            txt.SetSelection(rng[0], rng[1])

        elif (modifiers == 4 or modifiers == key.MOD_SHIFT):                                    # 4 (?) key.MOD_SHIFT (?)
            pos = txt.GetInsertionPoint()
            rng = list(txt.GetSelection())

            if rng[0] == rng[1] and ENTRY_SELECTION_EVENT in KeyboardEventUtils.__mLastEvt:
                del KeyboardEventUtils.__mLastEvt[ENTRY_SELECTION_EVENT]

            if ENTRY_SELECTION_EVENT in KeyboardEventUtils.__mLastEvt and KeyboardEventUtils.__mLastEvt[ENTRY_SELECTION_EVENT] == MASK_STARTED_LEFT_SELECTION:
                rng[0] = rng[0] + 1
            else:
                KeyboardEventUtils.__mLastEvt[ENTRY_SELECTION_EVENT] = MASK_STARTED_RIGHT_SELECTION
                rng[1] = rng[1] + 1

            txt.SetSelection(rng[0], rng[1])

        elif rawKey == key.LEFT:
            rng = list(txt.GetSelection())

            if rng[0] != rng[1]:
                txt.SetInsertionPoint(rng[0])
            else:
                txt.SetInsertionPoint(txt.GetInsertionPoint() - 1)

        elif rawKey == key.RIGHT:
            rng = list(txt.GetSelection())

            if rng[0] != rng[1]:
                txt.SetInsertionPoint(rng[1])
            else:
                txt.SetInsertionPoint(txt.GetInsertionPoint() + 1)

        elif rawKey == key.UP or rawKey == key.DOWN:
            pass

        elif rawKey == key.BACKSPACE:                                              
            pos = txt.GetInsertionPoint()
            if txt.GetStringSelection() == "":
                txt.SetValue(txt.GetValue()[:pos-1] + txt.GetValue()[pos:])
                txt.SetInsertionPoint(pos - 0x1)
            else:
                r = txt.GetSelection()
                txt.SetValue(txt.GetValue()[:r[0]] + txt.GetValue()[r[1]:])
                txt.SetInsertionPoint(pos)

        elif rawKey == key.DELETE:
            pos = txt.GetInsertionPoint()
            if txt.GetStringSelection() == "":
                txt.SetValue(txt.GetValue()[:pos] + txt.GetValue()[pos+1:])
            else:
                r = txt.GetSelection()
                txt.SetValue(txt.GetValue()[:r[0]] + txt.GetValue()[r[1]:])
            txt.SetInsertionPoint(pos)

        elif modifiers == key.MOD_CTRL and rawKey == key.A:
            txt.SelectAll()

        else:

            KeyboardEventUtils.__mLastEvt[ENTRY_ID] = txt.GetId()
            KeyboardEventUtils.__mLastEvt[ENTRY_KEY_EVENT] = evt
            return False

        KeyboardEventUtils.__mLastEvt[ENTRY_ID] = txt.GetId()
        KeyboardEventUtils.__mLastEvt[ENTRY_KEY_EVENT] = evt
        return True

SOURCE of INFOs key MODULE Python

Upvotes: 0

user2682863
user2682863

Reputation: 3218

You can bind the TextCtrl to wx.EVT_TEXT to capture changes to the value and wx.EVT_KILL_FOCUS to trigger an even when the focus changes. Alternatively you could bind it to wx.EVT_SET_FOCUS and save the current TextCtrl value and also bind to it wx.EVT_KILL_FOCUS to and compare the new value to see if it's changed.

------- EDIT -------

WxFormBuilder is fantastic tool for quickly creating basic UIs. It will also show you every event that you can bind to a widget by clicking on the 'events'` tab.

Upvotes: 0

Related Questions