Tkinter 检查哪个条目最后有焦点 [英] Tkinter check which Entry last had focus

查看:19
本文介绍了Tkinter 检查哪个条目最后有焦点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个具有我使用 Tkinter 创建的虚拟键盘的程序.启用了键盘的页面具有用户需要输入数据的条目小部件.我使用 pyautogui 作为虚拟键盘的一部分来模拟键盘按下,但我的问题是当用户按下键盘上的任何按钮时聚焦的小部件.由于每个键盘按钮在他们按下按键时都是一个 ttk.Button,因此该按钮具有焦点,而不是他们选择的他们试图将数据放入的 Entry 小部件.

I am working on a program that has a virtual keyboard I created using Tkinter. The pages that have the keyboard enabled have entry widgets where the users need to input data. I am using pyautogui as part of the virtual keyboard to simulate the keyboard presses, but my issue is the widget that is focused when a user presses on any of the buttons on the keyboard. Since each keyboard button is a ttk.Button when they press the keys, the button has the focus, and not the Entry widget they had selected they were trying to put data in.

因此,现在我有运行按键的方法,在按键之前调用特定的小部件以成为焦点.这是我现在拥有的代码:

As such right now I have the method which runs the keypresses, calling a specific widget to become the focus before it does the key press. Here's the code I have right now:

import tkinter as tk
from tkinter import ttk
import pyautogui

def drawKeyboard(parent):

    keyboardFrame = tk.Frame(parent)
    keyboardFrame.pack()

    keys = [
        [ ("Alpha Keys"),
          [ ('q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'),
            (' ', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'),
            ('capslock', 'z', 'x', 'c', 'v', 'b', 'n', 'm'),
            ('delete', 'backspace', 'home', 'end')
          ]
        ],
        [ ("Numeric Keys"),
          [ ('7', '8', '9'),
            ('4', '5', '6'),
            ('1', '2', '3'),
            (' ', '0', ' ')
          ]
        ]
    ]

    for key_section in keys:
        sect_vals = key_section[1]
        sect_frame = tk.Frame(keyboardFrame)
        sect_frame.pack(side = 'left', expand = 'yes', fill = 'both', padx = 10, pady = 10, ipadx = 10, ipady = 10)
        for key_group in sect_vals:
            group_frame = tk.Frame(sect_frame)
            group_frame.pack(side = 'top', expand = 'yes', fill = 'both')
            for key in key_group:
                key = key.capitalize()
                if len(key) <= 1:
                    key_button = ttk.Button(group_frame, text = key, width = 4)
                else:
                    key_button = ttk.Button(group_frame, text = key.center(5, ' '))
                if ' ' in key:
                    key_button['state'] = 'disable'
                key_button['command'] = lambda q=key.lower(): key_command(q)
                key_button.pack(side = 'left', fill = 'both', expand = 'yes')

def key_command(event):
    entry1.focus()
    pyautogui.press(event)
    return

root = tk.Tk()
entry1 = tk.Entry(root)
entry1.pack()
entry2 = tk.Entry(root)
entry2.pack()
drawKeyboard(root)
root.mainloop()

如果我想将数据输入到 entry2 中,显然手动调用 entry1.focus() 对我没有好处.如果我想将数据放入 entry1,调用 entry2.focus() 并没有什么好处.那么有没有办法让我每次按下我的一个按钮时检查哪个 Entry Widget 最后获得焦点?

Obviously manually calling entry1.focus() does me no good if I want to input data into entry2. And calling entry2.focus() does no good if I want to put data into entry1. So is there a way for me to every time one of my buttons is pressed check to see which Entry Widget last had focus?

我需要专门检查条目小部件,因为最终屏幕也会有一些单选按钮等.感谢您的时间

I need to check for specifically entry widgets as the final screen will also have some radio buttons and such. Thanks for your time

我对代码进行了快速更改,将 Shift 键替换为 Capslock 键.我意识到我的代码工作方式 Shift 永远不会真正工作,因为你不能完全按住它并按下另一个按钮.

I made a quick change to the code, exchanging the Shift key for the Capslock key. I realized that the way my code worked Shift would never actually work since you couldn't exactly hold it down and press another button.

推荐答案

您可以将属性 takefocus 设置为 False 以防止按钮获得焦点.这具有无法使用键盘遍历按钮的不幸副作用(这可能没问题,因为您处于无键盘的情况)

You can set the attribute takefocus to False to prevent the buttons from taking focus. This has the unfortunate side effect of not being able to traverse the buttons using the keyboard (which might be ok, since you're in a no-keyboard situation)

...
    key_button = ttk.Button(..., takefocus=False)
...
def key_command(event):
    entry = root.focus_get()
    entry.insert("end", event)
    pyautogui.press(event)
    return

另一种解决方案是在 <FocusIn> 事件上添加绑定,您可以在其中将小部件保存在全局变量中.

Another solution is to add a binding on the <FocusIn> event where you can save the widget in a global variable.

def key_command(event):
    focused_entry.insert("end", event)
    pyautogui.press(event)
    return

def remember_focus(event):
    global focused_entry
    focused_entry = event.widget

entry1.bind("<FocusIn>", remember_focus)
entry2.bind("<FocusIn>", remember_focus)

如果你有很多入口小部件,你可以在 Entry 类上做一个类绑定:

If you have many entry widgets, you can do a class binding on the Entry class instead:

root.bind_class("Entry", "<FocusIn>", remember_focus)

这篇关于Tkinter 检查哪个条目最后有焦点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆