简体   繁体   中英

Wxpython Detect Caps Lock status

I build a gui in wxpython (python-3). Someone knows how to detect if Caps Lock is on or off? Something like this code but with CapsLock.

event.CmdDown() 

It depends why you want to know if the Caps lock is active or not.
If you genuinely want to know if it is active you will have to specifically test for it.
If you need to warn about Capitals rather than Lowercase letters, then you can simply test for capital letters.
You need to read the details of wx.KeyEvent for the different event types. notably:

It's recommended to always use GetUnicodeKey and only fall back to GetKeyCode if GetUnicodeKey returned WXK_NONE meaning that the event corresponds to a non-printable special keys.

While both of these functions can be used with the events of wxEVT_KEY_DOWN , wxEVT_KEY_UP and wxEVT_CHAR types, the values returned by them are different for the first two events and the last one. For the latter, the key returned corresponds to the character that would appear in eg a text zone if the user pressed the key in it. As such, its value depends on the current state of the Shift key and, for the letters, on the state of Caps Lock modifier. For example, if A key is pressed without Shift being held down, wx.KeyEvent of type wxEVT_CHAR generated for this key press will return (from either GetKeyCode or GetUnicodeKey as their meanings coincide for ASCII characters) key code of 97 corresponding the ASCII value of a . And if the same key is pressed but with Shift being held (or Caps Lock being active), then the key could would be 65, ie ASCII value of capital A .

However for the key down and up events the returned key code will instead be A independently of the state of the modifier keys ie it depends only on physical key being pressed and is not translated to its logical representation using the current keyboard state. Such untranslated key codes are defined as follows:

For the letters they correspond to the upper case value of the letter. For the other alphanumeric keys (eg 7 or + ), the untranslated key code corresponds to the character produced by the key when it is pressed without Shift. Eg in standard US keyboard layout the untranslated key code for the key =/+ in the upper right corner of the keyboard is 61 which is the ASCII value of = . For the rest of the keys (ie special non-printable keys) it is the same as the normal key code as no translation is used anyhow. Notice that the first rule applies to all Unicode letters, not just the usual Latin-1 ones. However for non-Latin-1 letters only GetUnicodeKey can be used to retrieve the key code as GetKeyCode just returns WXK_NONE in this case.

To summarize: you should handle wxEVT_CHAR if you need the translated key and wxEVT_KEY_DOWN if you only need the value of the key itself, independent of the current keyboard state.

Here is some test code for isolating what you want to do.
Note the initial test for the capslock key only works on Linux using X. For other OS's you may have to use evdev

from evdev import InputDevice, ecodes

led = InputDevice('/dev/input/event5').leds(verbose=True) # eventX your keyboard
print("evdev :", led)

The test program:

import wx

import subprocess
x = subprocess.check_output('xset q | grep Caps', shell=True)
x = str(x.decode().strip()).split(':')
res = None
for idx, elem in enumerate(x):
    if "Caps " in elem:
        res = x[idx+1]

if "off" in res:
    capslock = False
else:
    capslock = True

class MyFrame(wx.Frame):
    def __init__(self, parent, id=wx.ID_ANY, title="", size=(360,100)):
        super(MyFrame, self).__init__(parent, id, title, size)
        self.panel = wx.Panel(self)
        self.panel.Bind(wx.EVT_KEY_DOWN, self.OnKey)
        self.panel.Bind(wx.EVT_CHAR, self.OnKey)
        self.Show()

    def OnKey(self, event):
        global capslock
        keycode = event.GetKeyCode()
        unicode = event.GetUnicodeKey()
        capital = ""
        if unicode >= 65 and unicode <= 90:
            capital = "Caps"
        print("key",keycode)
        print("uni",unicode, capital)
        if keycode == 311:
            print("Shift Lock Toggled")
            capslock = not capslock
            print(capslock)
        event.Skip()

if __name__ == "__main__":
    app = wx.App()
    frame = MyFrame(None,title="The Main Frame")
    app.MainLoop()

Note: how you unbundle the results from xset q may differ, depending on your OS and the version.

I found a nice way to check it:

from win32api import GetKeyState
from win32con import VK_CAPITAL
def caps_on():
    return GetKeyState(VK_CAPITAL) == 1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM