【问题标题】:Multimedia Keys in Python (Linux)Python 中的多媒体键 (Linux)
【发布时间】:2016-06-02 06:12:16
【问题描述】:

我想使用 Python 检测何时按下键盘上的 XF86Launch1 键。

我有一个带有蓝牙连接键盘的无头服务器。每当按下特定的多媒体键时,我想启动一个命令行程序。

目前,我正在使用:

import sys
import tty, termios

def getch():
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    try:
        tty.setraw(fd)
        ch = sys.stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return ch

print getch()

但它不会检测多媒体键。当我按下它们时,什么也没有打印出来。

有没有办法在无头 Ubuntu 机器上检测这些键 - 或者是在按键上启动程序的更好方法?

【问题讨论】:

    标签: python keyboard keyboard-shortcuts key-bindings


    【解决方案1】:

    您可以使用linux的输入设备api来读取它们,而不是尝试读取tty的stdin。

    在 linux 上,所有输入设备都显示为/dev/input 下的一个文件(例如/dev/input/event0),当这些文件中有一个read()s 时,返回指示何时按下和释放键的结构化数据。

    在 C 中,libevdev 库提供了一个包装器。在 python 中,您可以使用python-evdev library。也应该可以直接从输入设备读取(尽管您可能需要仔细阅读内核文档和源代码才能正确处理)。

    【讨论】:

      【解决方案2】:

      认为你的问题是多媒体键没有映射到终端输入。

      您可以通过运行 xev 来捕获密钥并运行 xmodmap 来将密钥映射到不同的输入来取得进展。

      或者,使用 TKinter 之类的工具,看看图形程序是否不收集按键。

      from Tkinter import *
      
      root = Tk()
      
      def key(event):
          print "pressed", repr(event.char)
      
      def callback(event):
          frame.focus_set()
      
      frame = Frame(root, width=100, height=100)
      frame.bind("<Key>", key)
      frame.bind("<Button-1>", callback)
      frame.pack()
      
      root.mainloop()
      

      另一种可能性是映射到 F 键而不是多媒体键。 (即 F9)


      编辑:对此的进一步研究导致了这两个链接:

      Extra Keyboard Keys

      Extra Keyboard Keys in Console

      控制台本身不支持多媒体键。但它确实支持自定义 F 键。 F30-F246 始终免费。不是映射到 XF86Launch1,而是映射到 F70。然后将 F70 映射到您的键盘映射中的键盘输入,或者使用您已经编写的 Python 脚本来处理它。

      【讨论】:

        【解决方案3】:

        pycopia 可能是一个选项。我将它与this 蓝牙按钮一起使用,它似乎工作得很好。当按钮进入睡眠状态然后回来时,我仍在努力让它重新连接到按钮。这是我正在使用的脚本的一部分:
        键盘.py:

        from pycopia.OS.Linux import Input
        from pycopia.OS.Linux import event
        
        class Satechi(Input.EventDevice):
            DEVNAME = 'Satechi'
        
            def register_callback(self, cb):
                self._callback = cb
        
            def poll(self):
                while 1:
                    ev = self.read()
                    if ev.evtype == event.EV_KEY:
                        self._callback(ev)
        
            read_handler = poll
        

        button.py

        from keyboard import Satechi
        
        def callback(event):
            pass #Do something fun
        
        if __name__ == '__main__':
            pm = Satechi()
            pm.find()
            pm.register_callback(callback)
        
            while 1:
                try:
                    pm.poll()
                except OSError:
                    pm = Satechi()
                    while True:
                        try:
                            pm.find()
                            pm.register_callback(callback)
                            break
                        except IOError:
                            pass
            pm.close()
        

        其中DEVNAME/proc/bus/input/devices 中的设备名称。
        您可以在回调中打印event 以找出您要查找的按钮的codevalue 是什么

        【讨论】:

        【解决方案4】:

        尝试循环读取xinput test &lt;id&gt; stdout 并捕获您需要的事件。

        这是 Bash 中的一些示例:

        #!/bin/bash
        
        keyboard_id=9 # 使用 xinput 查找您的键盘 id
        
        xinput 测试 $keyboard_id |而读线;做
            案例 $line in
                "按键 44") echo -e "\n == j 按下 ==" ;;
                "按键 45") echo -e "\n == k 按下 ==" ;;
            经社理事会
        完毕
        

        【讨论】:

          猜你喜欢
          • 2013-08-12
          • 1970-01-01
          • 2012-08-03
          • 2011-04-11
          • 2013-05-05
          • 1970-01-01
          • 2012-05-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多