【问题标题】:Tkinter check which Entry last had focusTkinter 检查哪个条目最后有焦点
【发布时间】:2017-12-27 12:26:51
【问题描述】:

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

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

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() 并没有好处。那么有没有办法让我每次按下我的一个按钮时检查哪个条目小部件最后有焦点?

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

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

【问题讨论】:

  • 这是我对 ttk 最大的不满之一,按钮会像这样窃取焦点。我不明白为什么有人会认为这是个好主意。
  • @BryanOakley 是的,这绝对是一个烦恼:\ 我一直在研究 pygtk,但不想实现它,因为我必须改变我的整个程序,这将是一个巨大的在这一点上很麻烦。
  • 您可以为按钮设置takefocus=False,但您也可以删除使用键盘遍历按钮的功能。如果您没有物理键盘,我想这不是问题。

标签: python tkinter


【解决方案1】:

您好,您会发现两种有用的方法,在这篇文章中进行了描述:

How do you check if a widget has focus in Tkinter?

  1. 将您的输入框绑定到 Enter 键。当按下 enter 时调用处理函数并将哪个条目具有焦点存储在全局可访问变量中,例如 self.entry_focus 以防您正在构建一个类或只是 entry_focus ,它将在模块范围级别的脚本开头声明。处理事件时,您可以通过访问传递给处理程序的事件对象来获取调用它的小部件的信息。为此使用 event.widget 和 root.focus_get 方法。

  2. 将 Enter 绑定到根项。然后使用 focus_get 方法检查每次按下 enter 时焦点在哪里,无论鼠标光标或焦点实际在哪里。

请参阅上面帖子中的代码。一切都会清楚。

祝你好运!

【讨论】:

    【解决方案2】:

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

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

    另一种解决方案是在&lt;FocusIn&gt; 事件上添加一个绑定,您可以将小部件保存在全局变量中。

    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 类上做一个类绑定:

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

    【讨论】:

    • 谢谢。这实际上非常有效(takefocus = False 部分)。我的程序最终会在平板上实现,所以我不用担心不能用键盘遍历按钮:)
    • 嘿布莱恩。在连接键盘的情况下,您能否将takefocus 改回True。只是一个假设的问题,但我同样感兴趣。或者可能有一个事件监视器,根据用户是尝试使用键盘还是屏幕键盘,将 takefocus 变为 True 或 False?
    • @SierraMountainTech:是的,您可以随时更改它。
    猜你喜欢
    • 1970-01-01
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-24
    • 2010-11-26
    • 1970-01-01
    • 2011-08-05
    相关资源
    最近更新 更多