如何编程双键按下以使非修饰键在我的程序中表现得像修饰键?

时间:2017-01-04 13:41:03

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

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

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

2 个答案:

答案 0 :(得分: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

我无法测试此代码(在学校计算机上工作),所以如果某些内容无效,请在评论中通知我,以便我可以解决。

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

答案 1 :(得分:0)

这是一个如何做到的Pyglet版本。
我基于常见的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。为self.key_table = {(107, 106) : 'a'}代表 k + j

很少有好处:

  • 无需跟踪延迟
  • 快速响应
  • 任何键都可以转换成自定义键盘布局的修饰符或地图,这意味着您可以单独将QWERTY转换为DWORAK。不确定为什么要这样,但是嘿..我的业务没有:D < / LI>
  • 覆盖默认键盘输入,因此您可以截取它们并随意执行任何操作。

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