简体   繁体   English

<Key>事件平台的关键代码是否独立?

[英]Are the key codes of a <Key> event platform-independent?

I wanted to create line numbers for my text editor, but it's a bit complicated: Tkinter adding line number to text widget 我想为我的文本编辑器创建行号,但它有点复杂: Tkinter在文本小部件中添加行号

So I decided to create a line and column counter, like in the IDLE . 所以我决定创建一个行和列计数器,就像在IDLE To achieve this goal, I decide to listen for the <Key> event generated on a tkinter.Text widget. 为了实现这个目标,我决定监听在tkinter.Text小部件上生成的<Key>事件。 I did not know which are the properties of an event object , so I decided to take a look in the source code of the Event class (one of the best tutorials :D), and I discovered there are 2 main properties that are interesting for my goal, that is keycode and char . 我不知道哪个是事件对象的属性,所以我决定看看Event类的源代码(最好的教程之一:D),我发现有2个主要属性是有趣的我的目标,那就是keycodechar

My question is, are this keycodes platform independents? 我的问题是,这个keycodes平台是独立的吗? I would like that my text editor work on all platforms without undefined behaviour, because of wrong interpretation of keycodes . 我希望我的文本编辑器可以在没有未定义行为的所有平台上工作,因为keycodes解释错误。

This is a simple practical functional example of what I would like to do: 这是我想做的一个简单实用的功能示例:

from tkinter import *

lines = 1
columns = 0

ARROWS = (8320768, 8124162, 8255233, 8189699)

def on_key_pressed(event=None):
    global columns, lines

    if event.keycode == 3342463: # return
        if columns > 0 and lines > 0:
            columns -= 1
            if columns < 0: # decrease lines if columns < 0
                columns = 0
                lines -= 1
        if columns == 0 and lines > 1:
            lines -= 1

    elif event.keycode == 2359309: # newline
        columns = 0
        lines += 1
    else:
        if event.keycode not in (ARROWS) and event.char != '':
            columns += 1

    print("Lines =", lines)
    print("Columns =", columns, '\n\n')
    print(event.keycode, ' = ', repr(event.char))

root = Tk()

text = Text(root)

text.pack(fill='both', expand=1)
text.bind('<Key>', on_key_pressed)

root.mainloop()

What are the problems of this approach (after answering my first question)? 这种方法有什么问题(在回答我的第一个问题后)?

On my Logitech keyboard with win7, the arrow keycodes are 37, 38, 39, and 40, with repr '', and return is 13, with repr '\\r'. 在带有win7的Logitech键盘上,箭头键码为37,38,39和40,其中repr为',返回为13,带有repr'\\ r'。 These keycode do not match either what you show, or the claims of this page . 这些键码与您显示的内容或此页面的声明不匹配。

However, the same page suggests using event.keysym or event.keysym_num. 但是,同一页面建议使用event.keysym或event.keysym_num。 What it does not point out is that the nums for non-unicode-character keys, like Shift, Up, F1, etc, are just below 2**16 (65536), in the 'private use area'. 它没有指出的是,非私人字符键的数字,如Shift,Up,F1等,在“私人使用区域”中仅低于2 ** 16(65536)。 The number for ascii chars are their ascii codes, which equal their unicode ordinals. ascii字符的数字是它们的ascii代码,等于它们的unicode序数。 I suspect that the number for all BMP unicode chars is their unicode ordinal (tk only encodes the BMP). 我怀疑所有BMP unicode字符的数字是它们的unicode序数(tk只编码BMP)。

The only use I can see for keycodes is to tell the difference between number keypad keys and the same key elsewhere. 我能看到的关键码的唯一用途是告诉数字键盘键和其他地方的相同键之间的区别。

The problems with your approach is that it will be almost impossible to compute the information you seek. 您的方法存在的问题是,几乎不可能计算您寻求的信息。 All the information you need is available by querying widget attributes and/or data so there's really no point in trying to keep track of the line and column yourself. 通过查询窗口小部件属性和/或数据,您可以获得所需的所有信息,因此尝试自己跟踪行和列是没有意义的。

This example is not an elegant solution, so I think it is better to "hardcode" keycodes depending on the operating system. 这个例子不是一个优雅的解决方案,所以我认为根据操作系统“硬编码”键码更好。

# 1. Generate keystrokes using Python + Tkinter.
# 2. Save needed keycodes in the dictionary.
# 3. Use dictionary with keycodes to handle keystrokes independently from
#    operating system, language or (maybe?) keyboard model.
# This is not an elegant solution, so I think it is better to "hardcode"
# keycodes depending on the operating system.
import tkinter as tk

def keystroke(event):
    dict[event.keycode] = event.keysym  # save keycodes into the dictionary

def keyboardevent(str):
    # Code that simulated 'key' being pressed on keyboard
    temp.after(10, lambda: temp.event_generate('<Key-{}>'.format(str)))

temp = tk.Tk()
temp.withdraw()  # remove the window from the screen (without destroying it)
temp.bind('<Key>', keystroke)
dict = {}  # dictionary of the needed keycodes
keyboardevent('w')  # generate needed keyboard events
keyboardevent('s')
keyboardevent('a')
keyboardevent('d')
temp.after(20, temp.destroy)  # this is not needed anymore
temp.mainloop()

# Start your code here
def keys_handler(event):
    if event.keycode in dict:
        print(dict[event.keycode])

root = tk.Tk()
root.focus_force()
root.bind('<Key>', keys_handler)
root.mainloop()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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