Intercept and modify KeyEvents?

186 views
Skip to first unread message

cbeytas

unread,
Jun 7, 2017, 3:38:23 PM6/7/17
to wxPython-users
I have a TextCtrl for which I'm trying to intercept EVT_CHAR events and modify them so that they are uppercase.
The handler seems to be functioning properly. After it is modified the event.GetUnicodeKey() method returns the proper upper-case code, but the TextCtrl still gets the lower-case characters.
Am I doing something obviously wrong here?

class MyPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
       
        wx.StaticText(self, label="Edit Control:", pos=(10,10))
        self.edit = wx.TextCtrl(self, pos=(150, 10), size=(140,-1))
        self.edit.Bind(wx.EVT_CHAR, self.OnChar)

    def OnChar(self, event):
        char = unichr(event.GetUnicodeKey())
        upper_char = char.upper()
        if upper_char != char:
            event.SetUnicodeKey(ord(upper_char))
        event.Skip()


Dietmar Schwertberger

unread,
Jun 7, 2017, 4:16:56 PM6/7/17
to wxpytho...@googlegroups.com
On 6/7/17 8:11 PM, cbeytas wrote:
> I have a TextCtrl for which I'm trying to intercept EVT_CHAR events
> and modify them so that they are uppercase.
> The handler seems to be functioning properly. After it is modified the
> event.GetUnicodeKey() method returns the proper upper-case code, but
> the TextCtrl still gets the lower-case characters.
Try without the event.Skip() as you are handling it already.

Regards,

Dietmar

Dietmar Schwertberger

unread,
Jun 7, 2017, 4:18:32 PM6/7/17
to wxpytho...@googlegroups.com
P.S.: sorry: add the character to the text control instead of using
event.SetUnicodeKey(...)

cbeytas

unread,
Jun 7, 2017, 8:41:14 PM6/7/17
to wxPython-users, mail...@schwertberger.de
Right. It works if I do:
    start, stop = textCtrl.GetSelection()
    textCtrl.Replace(start, stop, upper_char)
    event.Skip(False)

I'm not confident that would cover all possible cases, cross-platform. I'm just wondering why modifying the event doesn't work.
Perhaps something I don't understand with how events are processed? Maybe the event handler is receiving a clone and not the actual event?
I've tried to generate another wx.KeyEvent with the upper case character and posting that to the TextCtrl but that didn't work either.
I've also tried cloning the event but seems that the event.Clone() method doesn't work at all.

Igor Korot

unread,
Jun 7, 2017, 9:16:13 PM6/7/17
to wxpytho...@googlegroups.com, mail...@schwertberger.de
Hi,



On Jun 7, 2017 8:41 PM, "cbeytas" <cbe...@hotmail.com> wrote:

If you have a recent wxWidgets compiled for wxpython, this functionality is already present.
Just check the docs.

Thank you.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

David Woods

unread,
Jun 7, 2017, 9:58:40 PM6/7/17
to wxpytho...@googlegroups.com
Check EVT_KEY_UP or maybe EVT_KEY_DOWN, as one of these events may be the one responsible for actually placing the character.

David

cbeytas

unread,
Jun 7, 2017, 11:33:40 PM6/7/17
to wxPython-users
Actually found a post which sort of explains that modifying KeyEvents won't work.

http://wxpython-users.1045709.n5.nabble.com/Little-problems-tp2297400p2297405.html

This is a surprise to me since I can modify MouseEvents (ie. adjust the .X and .Y attributes) and they take effect and are propagated to controls.
Maybe difference between regular Events and CommandEvents.

James Scholes

unread,
Jun 8, 2017, 5:30:37 AM6/8/17
to wxpytho...@googlegroups.com
cbeytas wrote:
> Right. It works if I do:
> start, stop = textCtrl.GetSelection()
> textCtrl.Replace(start, stop, upper_char)
> event.Skip(False)
>
> I'm not confident that would cover all possible cases, cross-platform.

I don't really feel like modifying key events is what you want to do
here. Your goal - have all text in a wx.TextCtrl be uppercase. So what
happens when a user pastes text into the control or you set the contents
programmatically? You'll end up with a mix of upper and original case text.

Instead, it would probably be better to bind a wx.EVT_TEXT handler and,
when the text in the control is changed, convert the whole thing to
uppercase, restoring the selection if necessary. See this Stack
Overflow question for an example:

https://stackoverflow.com/questions/1241942/wxpython-textctrl-transform-to-uppercase
--
James Scholes
http://twitter.com/JamesScholes

cbeytas

unread,
Jun 8, 2017, 9:46:58 AM6/8/17
to wxPython-users, ja...@jls-radio.com
It's all about aesthetics.. Using EVT_TEXT can cause ugly flickering with the lower-case character showing up for a split second before being replaced. Strangely enough it doesn't happen on all machines.
I also want to block certain characters in the EVT_CHAR handler. EVT_TEXT happens after the character has been added to the control (possibly replacing the current selection). This wreaks havoc with the cursor position.
I already trap EVT_PASTE and manage clipboard pasting manually.
Reply all
Reply to author
Forward
0 new messages