Wxpython检测大写锁定状态

Wxpython Detect Caps Lock status

我在 wxpython (python-3) 中构建了一个图形用户界面。有人知道如何检测大写锁定是打开还是关闭? 类似于这段代码,但带有 CapsLock。

event.CmdDown() 

这取决于您想知道 Caps lock 是否处于活动状态的原因。
如果您真的想知道它是否处于活动状态,则必须专门对其进行测试。
如果您需要警告大写字母而不是小写字母,那么您可以简单地测试大写字母。
对于不同的事件类型,您需要阅读 wx.KeyEvent 的详细信息。特别是:

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 e.g. 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, i.e. 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 i.e. 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 (e.g. 7 or + ), the untranslated key code corresponds to the character produced by the key when it is pressed without Shift. E.g. 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 (i.e. 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.

这里是一些测试代码,用于隔离你想做的事情。
请注意,大写锁定键的初始测试仅适用于使用 X 的 Linux。对于其他 OS,您可能必须使用 evdev

from evdev import InputDevice, ecodes

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

测试程序:

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

注意:根据您的 OS 和版本,您对 xset q 的结果进行拆分的方式可能会有所不同。

我找到了一个很好的检查方法:

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