每次用鼠标单击Tkinter条目时,打开一个数字键盘



我的职业不是程序员,目前正尝试使用python的tkinter模块编写一个小型应用程序,以便在平板电脑上使用。我希望每次点击/触摸抖音输入小部件时都会弹出一个数字键盘。我在stackoverflow上发现了以下代码;NumpadEntry;类(继承自tk.Entry(,它几乎完全符合我的要求。然而,一旦numpad窗口关闭,在我点击另一个窗口或使用中间的第二个条目之前,无法通过再次点击NumpadEntry小部件来重新打开它。

示例代码:

import tkinter as tk
def enumerate_row_column(iterable, num_cols):
for idx, item in enumerate(iterable):
row = idx // num_cols
col = idx % num_cols
yield row,col,item
class NumpadEntry(tk.Entry):
def __init__(self,parent=None,**kw):
tk.Entry.__init__(self,parent,**kw)
self.bind('<FocusIn>', self.numpadEntry)
self.bind('<FocusOut>',self.numpadExit)
self.edited = False
def numpadEntry(self,event):
if self.edited == False:
print("You Clicked on me")
self['bg']= '#ffffcc'
self.edited = True
new = numPad(self)
else:
self.edited = False
def numpadExit(self,event):
self['bg']= '#ffffff'
class numPad(tk.simpledialog.Dialog):
def __init__(self,master=None,textVariable=None):
self.top = tk.Toplevel(master=master)
self.top.protocol("WM_DELETE_WINDOW",self.ok)
self.createWidgets()
self.master = master

def createWidgets(self):
btn_list = ['7',  '8',  '9', '4',  '5',  '6', '1',  '2',  '3', '0',  'Close',  'Del']
# create and position all buttons with a for-loop
btn = []
# Use custom generator to give us row/column positions
for r,c,label in enumerate_row_column(btn_list,3):
# partial takes care of function and argument
cmd = lambda x = label: self.click(x)
# create the button
cur = tk.Button(self.top, text=label, width=10, height=5, command=cmd)
# position the button
cur.grid(row=r, column=c)                                              
btn.append(cur)

def click(self,label):
print(label)
if label == 'Del':
currentText = self.master.get()
self.master.delete(0, tk.END)
self.master.insert(0, currentText[:-1])
elif label == 'Close':
self.ok()
else:
currentText = self.master.get()
self.master.delete(0, tk.END)
self.master.insert(0, currentText+label)
def ok(self):
self.top.destroy()
self.top.master.focus()
class App(tk.Frame):
def __init__(self,parent=None,**kw):
tk.Frame.__init__(self,parent,**kw)
self.textEntryVar1 = tk.StringVar()
self.e1 = NumpadEntry(self,textvariable=self.textEntryVar1)
self.e1.grid()
self.textEntryVar2 = tk.StringVar()
self.e2 = NumpadEntry(self,textvariable=self.textEntryVar2)
self.e2.grid()

if __name__ == '__main__':
root = tk.Tk()
root.geometry("200x100")
app = App(root)
app.grid()
root.mainloop()

我试图以某种方式再次将编辑后的变量设置为False,例如在numpadExit函数中:

def numpadExit(self,event):
self['bg']= '#ffffff'
self.edited == False

但这只会导致numpad每次关闭时都会打开。

我还尝试使用lambda或将";FocusIn";至";输入";此处:

self.bind('<FocusIn>', self.numpadEntry)

但这也没有奏效。

恐怕这个问题有些超出了我目前对python的理解:(因此,我们将非常感谢您的帮助。非常感谢。

问题的出现是因为您绑定了焦点向内和向外,所以您必须关注另一个条目,然后才能再次关注第一个条目。相反,绑定到<Button-1>,单击鼠标左键即可。

用CCD_ 2子类CCD_ 3代替CCD_。这也消除了对simpledialog导入的需要
我已将grab_set添加到数字键盘窗口中。这会将所有事件导向它,这样用户就无法在numpad打开时与主窗口进行交互。这意味着您不必担心用户重复单击条目并创建大量窗口。添加focus_force()会在创建numpad窗口时使其成为焦点。我删除了edited变量,因为它不再需要,并略微更改了numPadok方法,因此当numpad被破坏时,条目颜色会发生变化。

class NumpadEntry(tk.Entry):
def __init__(self,parent=None,**kw):
tk.Entry.__init__(self,parent,**kw)
self.bind('<Button-1>', self.numpadEntry)
def numpadEntry(self,event):
print("You Clicked on me")
self['bg']= '#ffffcc'
new = numPad(self)
def numpadExit(self):
self['bg']= '#ffffff'
class numPad(tk.Toplevel):
def __init__(self,master=None,textVariable=None):
tk.Toplevel.__init__(self, master=master)
self.protocol("WM_DELETE_WINDOW",self.ok)
self.createWidgets()
self.master = master
self.grab_set()
self.focus_force()

def createWidgets(self):
btn_list = ['7',  '8',  '9', '4',  '5',  '6', '1',  '2',  '3', '0',  'Close',  'Del']
# create and position all buttons with a for-loop
btn = []
# Use custom generator to give us row/column positions
for r,c,label in enumerate_row_column(btn_list,3):
# partial takes care of function and argument
cmd = lambda x = label: self.click(x)
# create the button
cur = tk.Button(self, text=label, width=10, height=5, command=cmd)
# position the button
cur.grid(row=r, column=c)                                              
btn.append(cur)

def click(self,label):
print(label)
if label == 'Del':
currentText = self.master.get()
self.master.delete(0, tk.END)
self.master.insert(0, currentText[:-1])
elif label == 'Close':
self.ok()
else:
currentText = self.master.get()
self.master.delete(0, tk.END)
self.master.insert(0, currentText+label)
def ok(self):
self.master.numpadExit()
self.destroy()

最新更新