【问题标题】:How do I program a double key press to make a non-modifier key behave like a modifier key within my program?如何对双按键进行编程以使非修饰键在我的程序中表现得像修饰键?
【发布时间】:2017-05-18 19:52:42
【问题描述】:

我正在编写一个打字程序,其中包含的字符比标准键盘上的字符多得多。为了实现这一点,我需要将一些字母键转换为修饰键CTRL+A。例如 f+j 将输出 a。键入 f 然后 j 对用户来说很慢,我需要他们能够按 fj同时接收一个输出。如果在程序运行时停止某些键盘的正常功能,这很好(甚至更可取)。

我研究了 pygame Keydown,但它似乎只具有增加按键重复而不停止按键输出的功能。 Pyglet 也是一种可能,但它没有关于如何制作附加修饰键的确切文档。我能弄清楚的唯一方法是不断扫描整个键盘以查看是否按下了任何键,但这不会确定按下键的顺序并且会为用户产生错误,因为用户按下 f 然后j 将与用户按 j 然后 f 读取相同,并且我只需要 f 然后 j 组合被系统理解为击键。

【问题讨论】:

  • PyGame中使用KEYDOWN,您可以获得一把钥匙,保存并开始计算时间 - 如果您在短时间内收到第二把钥匙,那么您可以将它们视为组合。顺便说一句:您还可以使用KEYUP 来检查第一个键是否已释放。
  • Qt 中有 keypress- 和 keyrelease- 事件。像这样,您可以按按下的顺序存储键,并在它们被释放时相应地删除它们。也许这个答案也有帮助:stackoverflow.com/a/16044380/3767239

标签: python keyboard keyboard-shortcuts keyboard-events pyglet


【解决方案1】:

这是一些用 Python 2 编写的用于快速连续打印按键的简单代码。它应该可以轻松修改以满足您的需求:

import pygame, sys
pygame.init()
screen = pygame.display.set_mode([500,500])
clock = pygame.time.Clock()

combokeys = []
timer = 0
ACCEPTABLE_DELAY = 30 #0.5 seconds

while 1:
    clock.tick(60)
    timer += 1
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if timer <= ACCEPTABLE_DELAY:
                combokeys.append(event.unicode)
            else:
                combokeys = [event.unicode]
            timer = 0
            print combokeys

我无法测试此代码(在学校计算机上工作),所以如果有问题,请在 cmets 中通知我,以便我修复它。

您可以更改为 ACCEPTABLE_DELAY 指定的值,以更改在某些东西被视为不同的组合键之前的延迟。延迟应该是 (ACCEPTABLE_DELAY/60) 秒。

【讨论】:

  • 你在if timer &lt;= ACCEPTABLE_DELAY之前设置了timer = 0,所以你总是有if 0 &lt;= ACCEPTABLE_DELAY——你需要不同的东西或者timer = 0必须在不同的地方。
  • 糟糕!你说得对,我是想把它放在后面,而不是放在前面。谢谢!我现在就编辑它...
【解决方案2】:

这是一个 Pyglet 版本,您可以这样做。
我基于 common GUI class that I use often here on SO 编写它,因为它是模块化的并且更易于构建,而代码在 40 行之后不会变得混乱。

import pyglet
from pyglet.gl import *

key = pyglet.window.key

class main(pyglet.window.Window):
    def __init__ (self):
        super(main, self).__init__(800, 800, fullscreen = False)
        self.x, self.y = 0, 0

        #self.bg = Spr('background.jpg')
        self.output = pyglet.text.Label('',
                          font_size=14,
                          x=self.width//2, y=self.height//2,
                          anchor_x='center', anchor_y='center')

        self.alive = 1
        self.pressed = []
        self.key_table = {213 : 'a'}

    def on_draw(self):
        self.render()

    def on_close(self):
        self.alive = 0

    def on_key_release(self, symbol, modifiers):
        if symbol == key.LCTRL:
            pass # Again, here's how you modify based on Left CTRL for instance

        ## All key presses represents a integer, a=97, b=98 etc.
        ## What we do here is have a custom key_table, representing combinations.
        ## If the sum of two pressed matches to our table, we add that to our label.
        ## - If no match was found, we add the character representing each press instead. 
        ##   This way we support multiple presses but joined ones still takes priority.

        key_values = sum(self.pressed)
        if key_values in self.key_table:
            self.output.text += self.key_table[key_values]
        else:
            for i in self.pressed:
                self.output.text += chr(i)
        self.pressed = []

    def on_key_press(self, symbol, modifiers):
        if symbol == key.ESCAPE: # [ESC]
            self.alive = 0
        elif symbol == key.LCTRL:
            pass # Modify based on left control for instance
        else:
            self.pressed.append(symbol)

    def render(self):
        self.clear()
        #self.bg.draw()

        self.output.draw()

        self.flip()

    def run(self):
        while self.alive == 1:
            self.render()

            # -----------> This is key <----------
            # This is what replaces pyglet.app.run()
            # but is required for the GUI to not freeze
            #
            event = self.dispatch_events()

x = main()
x.run()

它可能看起来像很多代码,尤其是对于 Pygame 的答案。但是您也可以将其压缩到大约 15 行,但是如果您尝试进一步构建,代码会再次变得混乱。

希望这可行。现在我还没有考虑过这个数学..两个重复的键组合可能会产生与另一个键表示相同的值,只需将字典键 213 替换为元组键,例如 @ 987654324@ 代表 k+j

几个好处:

  • 无需跟踪延迟
  • 快速响应
  • 任何键都可以转换为修饰符或映射自定义键盘布局,这意味着您可以将 QWERTY 转换为 DWORAK 仅用于此应用程序。不知道为什么要这样做,但是嘿.. 不关我的事 :D
  • 覆盖默认键盘输入,因此您可以截取它们并使用它们做任何您想做的事情。

编辑:一个很酷的功能是注册每个键,但用连接的组合替换最后一个字符。这也是所有手动工作,因为键盘不是用来做双键表示的,而且它更多一个图形的想法..但会很酷:)

【讨论】:

    猜你喜欢
    • 2016-07-15
    • 2019-05-04
    • 2011-12-23
    • 1970-01-01
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多