我是python和tkinter的新手。我一直在努力提高我的技能,所以我可以开始编程我的覆盆子Pi。我当前的问题让我感到难过:当我点击Entry字段时,我想调出一个对话框(屏幕键盘)。
我已经尝试了几种方法来实现这一目标。我可以让键盘在开头显示一次或者根本不显示。但不是点击事件。我知道键盘类正在使用它,所以它必须与我如何调用它(popout.py的第29行)。根据我尝试实现的方式,我收到两条错误消息之一:
Exception in Tkinter callback
Traceback (most recent call last):
File "E:\Programs\Python3\lib\tkinter\__init__.py", line 1533, in __call__
return self.func(*args)
TypeError: keyboard() takes from 1 to 3 positional arguments but 4 were given
或
Exception in Tkinter callback
Traceback (most recent call last):
File "E:\Programs\Python3\lib\tkinter\__init__.py", line 1533, in __call__
return self.func(*args)
TypeError: 'Keyboard' object is not callable
我真的不明白为了获得这些例外会发生什么。以下是我的代码:
Popup.py
import tkinter as tk
import keyboard as k
#
from time import sleep
# needs Python25 or higher
from functools import partial
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.pack()
#variable to update counter text
self.num = tk.StringVar()
self.create_widgets()
def create_widgets(self):
# button to start counting
self.startbtn = tk.Button(self)
self.startbtn["text"] = "Start counting\n(Click)"
self.startbtn["command"] = self.counting
self.startbtn.pack(side="top")
#Label to view counter
self.counter = tk.Label(self, textvariable=self.num)
self.counter.pack()
#Entry box
self.e = tk.StringVar()
self.entry = tk.Entry(self, textvariable=self.e)
#launch_kbd = partial(self.keyboard, "MyKeyboard", self.e)
#self.entry.bind("<Button-1>", launch_kbd)
self.entry.bind("<Button-1>", k.Keyboard(self, "MyKeyboard", self.e))
self.entry.pack()
#Exit
self.quit = tk.Button(self, text="Quit", fg="red", command=root.destroy)
self.quit.pack(side="bottom")
#count for 10 seconds
def counting(self):
self.startbtn["state"] = "disabled"
root.update()
#loop from 1-10
for x in range(1,11):
self.num.set(str(x)) #update the label's variable
root.update() #important to make changes visible
sleep(1) #sleep for 1 second
#Clear text when done
self.num.set("")
self.startbtn["state"] = "enabled"
root.update()
#def keyboard(self, title=None, target=None):
# k.Keyboard(self, title, target)
'''
This starts the root window
'''
root = tk.Tk()
root.title("myGUI")
root.geometry("200x100")
app = Application(master=root)
app.mainloop()
keyboard.py
'''
# Built with examples from:
- http://effbot.org/tkinterbook/tkinter-dialog-windows.htm
- https://www.daniweb.com/programming/software-development/threads/300867/on-screen-keyboards-in-tkinter
# Desc: Creates a pop-up on-screen Keyboard for text entry.
Writes entry to Target upon pressing Enter.
'''
# use tkinter for GUI application
import tkinter as tk
# used for button click
from functools import partial
class Keyboard(tk.Toplevel):
def __init__(self, parent, title=None, target=None):
tk.Toplevel.__init__(self, parent, bg='black')
# associate this window with a parent window
self.transient(parent)
if title:
self.title(title)
if target:
self.target = target
self.init_txt = target.get()
self.parent = parent
body = tk.Frame(self)
self.body(body)
body.pack(padx=5, pady=5)
self.buttonbox()
#make the dialog modal
self.grab_set()
# safely handle WM_DELETE_WINDOW event
self.protocol("WM_DELETE_WINDOW", self.close)
# position the dialog relative to the parent window
self.geometry("+%d+%d" % (parent.winfo_rootx()+50, parent.winfo_rooty()+50))
# Hold captive control until window is closed
# prevent parent from accepting input while window is open
self.wait_window(self)
# END Init
def body(self, master):
#Text input at the top
self.txt = tk.StringVar()
self.txt.set(self.init_txt)
self.tx = tk.Entry(self, bg='black', fg='white', insertbackground='gray', insertwidth=2, textvariable=self.txt)
self.tx.focus_set()
self.tx.pack(fill="x", padx=5, pady=5)
def buttonbox(self):
# create a frame for the keypad buttons
bf = tk.Frame(self)
bf.pack()
# button layout
btn_list = [
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P',
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';',
'Z', 'X', 'C', 'V', 'B', 'N', 'M', ',', '.', '?',
'Num', '+', '-', ' ', ' ', ' ', '<-', '->', 'BKS', 'ETR', ]
# create and position all buttons with a for-loop
# r, c used for row, column grid values
r = 1
c = 0
n = 0
# list(range()) needed for Python3
btn = list(range(len(btn_list)))
for label in btn_list:
# partial takes care of function and argument
cmd = partial(self.click, label)
# create the button (and style it)
btn[n] = tk.Button(bf, text=label, width=5, height=3, command=cmd, bg='#333333', fg='white', activebackground='#666666', activeforeground='white')
# position the button
btn[n].grid(row=r, column=c)
# increment button index
n += 1
# update row/column position
c += 1
if c > 9:
c = 0
r += 1
def click(self, btn):
if btn == 'Num':
# Switch to number pad
pass
elif btn == '<-':
# Move cursor to the left 1 character
self.tx.icursor(self.tx.index('insert')-1)
elif btn == '->':
# Move cursor to the right 1 character
#icursor(index)
self.tx.icursor(self.tx.index('insert')+1)
elif btn == 'BKS':
# truncate entry by 1 character
self.tx.delete(self.tx.index('insert')-1)
elif btn == 'ETR':
# return entered value to the input
self.apply()
self.close()
else:
# DEFAULT: append entry with btn
self.tx.insert('insert', btn)
def close(self, event=None):
# put focus back to the parent window
self.parent.focus_set()
self.destroy()
def apply(self):
self.target.set(self.tx.get())
# if called directly
if __name__ == "__main__":
root = tk.Tk()
t = tk.StringVar()
k = Keyboard(root, "MyKeyboard", target=t)
print(t.get())
答案 0 :(得分:0)
使用Button-1
函数将参数传递给Popup.py
事件函数。
在self.entry.bind("<Button-1>", k.Keyboard(self, "MyKeyboard", self.e))
的第33行,更改:
self.entry.bind("<Button-1>", lambda event: k.Keyboard(self, "MyKeyboard", self.e))
为:
self.startbtn["state"] = "enabled"
此外,counting
方法下的self.startbtn["state"] = "normal"
应为Message