无法从变量中获取键盘键
Cannot get keyboard key from variable
所以我正在尝试制作一个可以 hold/autoclick 键盘按键的程序。
问题是,程序不理解我给它的变量(从 Tkinter Entry 获得)要按下的键。
当我用pynput按键时,提示我没有给它赋值:
AttributeError: 'str' object has no attribute 'value'
当我使用 pyautogui 按键时,它什么也没做,甚至 return 都没有报错。
部分代码无效:
#Autoclicking keyboard key (using pynput) (not working)
#hold = whether to autoclick or hold key
#clkdel = delay between keyboard presses
#keyprsd = key to be pressed (tk.StringVar)
#lf7 = listener for when to start/stop
if int(hold.get()) == 1:
print('Starting keyboard pressing...')
while self.run == True:
print('Pressed')
master.after(clkdel, keyct.press(keyprsd.get()))
lf7.stop()
完整代码:
import tkinter as tk
from pynput.keyboard import Key, Listener
from pynput.mouse import Button, Controller
from pynput import keyboard
import pyautogui
class GUI:
def __init__(self, master):
#Defining variables
hold = tk.IntVar()
keyprsd = tk.StringVar()
self.run = False
msbt = tk.IntVar()
mousect = Controller()
keyct = Controller()
#Creating main window
master = master
master.title('Key Clicker')
master.geometry('250x250')
master.resizable(False, False)
#Creating radio buttons:
#Autoclick button
self.autoclick = tk.Radiobutton(master, text='Autoclick', variable=hold, value=1)
self.autoclick.grid(row=0, column=0, sticky='en', padx=30, pady=5)
#Hold button
self.holdbt = tk.Radiobutton(master, text='Hold', variable=hold, value=2)
self.holdbt.grid(row=0, column=1, sticky='wn', padx=0, pady=5)
#Creating keyboard button label
self.kbtlabel = tk.Label(master, textvariable=keyprsd, width=10, bg='Light Blue')
self.kbtlabel.grid(row=1, column=0, sticky='wens')
#Creating keyboard button detection:
#Functions to detect key to be pressed
def lforsetkey():
lst = Listener(on_press=ksetcall)
lst.start()
def ksetcall(key):
print('{} was pressed'.format(key))
keyprsd.set(key)
return False
#Functions to detect when to start and stop autoclicking/holding
def f7press(key):
print('{} was pressed'.format(key))
if key == keyboard.Key.f7:
self.run = False
if key == keyboard.Key.f6:
self.run = True
stmouse()
if key == keyboard.Key.f8:
self.run = True
stkey()
def lforf7():
global lf7
lf7 = Listener(on_press=f7press)
lf7.start()
lforf7()
#Creating key selection button
self.kbtsel = tk.Button(master, text='Click and press a key', command=lforsetkey)
self.kbtsel.grid(row=2, column=0, sticky='wen', padx=0)
#Creating list for mouse buttons
self.mslft = tk.Radiobutton(master, text='Left Click', variable=msbt, value=1)
self.mslft.grid(row=1, column=1, sticky='en', padx=10)
self.msrft = tk.Radiobutton(master, text='Right Click', variable=msbt, value=2)
self.msrft.grid(row=2, column=1, sticky='en', padx=10)
#Creating autoclick frequency label
self.clklb = tk.Label(master, text='Autoclick frequency (ms)')
self.clklb.grid(row=3, column=0)
#Creating autoclick frequency entry
self.clkent = tk.Entry(master)
self.clkent.grid(row=3, column=1)
#Creating mouse autoclick button
def stmouse():
self.run = True
lforf7()
try:
clkdel = int(self.clkent.get())
except ValueError:
print('Value Error')
#Autoclicking left button
if int(msbt.get()) == 1 and int(hold.get()) == 1:
print('Starting mouse autoclick...')
while self.run == True:
print('Clicked')
master.after(clkdel, mousect.click(Button.left))
lf7.stop()
#Autoclicking right button
elif int(msbt.get()) == 2 and int(hold.get()) == 1:
print('Starting mouse autoclick...')
while self.run == True:
print('Clicked')
master.after(clkdel, mousect.click(Button.right))
lf7.stop()
#Holding left button
elif int(msbt.get()) == 1 and int(hold.get()) == 2:
print('Starting mouse holding...')
while self.run == True:
pyautogui.mouseDown(button='left')
lf7.stop()
pyautogui.mouseUp(button='left')
#Holding right button
elif int(msbt.get()) == 2 and int(hold.get()) == 2:
print('Starting mouse holding...')
while self.run == True:
pyautogui.mouseDown(button='right')
lf7.stop()
pyautogui.mouseUp(button='right')
else:
print('Error')
self.msbt = tk.Button(master, text='Click to start holding/autoclicking mouse', command=stmouse)
self.msbt.grid(row=4, column=0, columnspan=2, sticky='swe', pady=5)
#Creating keyboard button
def stkey():
#Setting up variables and starting listener
self.run = True
lforf7()
try:
clkdel = int(self.clkent.get())
except ValueError:
print('Value Error')
#Autoclicking keyboard key (using pynput) (not working)
#hold = whether to autoclick or hold key
#clkdel = delay between keyboard presses
#keyprsd = key to be pressed (tk.StringVar)
#lf7 = listener for when to start/stop
if int(hold.get()) == 1:
print('Starting keyboard pressing...')
while self.run == True:
print('Pressed')
master.after(clkdel, keyct.press(keyprsd.get()))
lf7.stop()
#Holding keyboard key (also not working)
elif int(hold.get()) == 2:
print('Holding keyboard...')
while self.run == True:
pyautogui.keyDown(keyprsd.get())
lf7.stop()
print('Stopping')
pyautogui.keyUp(keyprsd.get())
else:
print('Error')
self.kbt = tk.Button(master, text='Click to start holding/autoclicking keyboard', command=stkey)
self.kbt.grid(row=5, column=0, columnspan=2, sticky='swe', pady=5)
root = tk.Tk()
GUI(root)
root.mainloop()
你的主要问题是你只导入了鼠标控制器
from pynput.mouse import Button, Controller
你用它来做鼠标和键盘
mousect = Controller()
keyct = Controller()
但是他们有不同的控制器,它们的工作方式不同。
键盘控制器可以获取字符串,但鼠标控制器需要带有 .value
的对象
你应该使用 differenet 控制器
from pynput import mouse
from pynput import keyboard
mousect = mouse.Controller()
keyct = keyboard.Controller()
这解决了主要问题。
但还有其他问题 - after()
(类似于 command=
和 bind()
)需要没有参数的函数名称,您可以使用 lambda
(如 command=
或 bind()
) 或者你必须在函数名后使用参数
master.after(clkdel, keyct.press, keyprsd.get())
master.after(clkdel, mousect.click, Button.left)
master.after(clkdel, mousect.click, Button.right)
顺便说一句: 另一个问题是您的代码不可读。您应该将嵌套函数移到 class 之外或创建 class 方法,这样您就不需要 global
而需要 self.
。您还可以使用更具可读性的名称 - 即。 key_controller
比 keyct
.
更具可读性
参见:PEP 8 -- Style Guide for Python Code
编辑:
Listener
为特殊对象提供有关密钥的信息,然后将其作为字符串放入 StringVar
中,稍后您从 StringVar
中获取它作为字符串并在 [=30 中使用该字符串=] - 它可以用于普通键但不适用于特殊键。
您必须保留原始对象并在 press()
中将此对象用于所有键(普通键和特殊键)。即
def ksetcall(key):
self.key = key # keep original object
print('{} was pressed'.format(key))
keyprsd.set(key)
return False
以后
keyct.press(self.key)
而不是keyct.press(keyprsd.get())
所以我正在尝试制作一个可以 hold/autoclick 键盘按键的程序。 问题是,程序不理解我给它的变量(从 Tkinter Entry 获得)要按下的键。
当我用pynput按键时,提示我没有给它赋值:
AttributeError: 'str' object has no attribute 'value'
当我使用 pyautogui 按键时,它什么也没做,甚至 return 都没有报错。
部分代码无效:
#Autoclicking keyboard key (using pynput) (not working)
#hold = whether to autoclick or hold key
#clkdel = delay between keyboard presses
#keyprsd = key to be pressed (tk.StringVar)
#lf7 = listener for when to start/stop
if int(hold.get()) == 1:
print('Starting keyboard pressing...')
while self.run == True:
print('Pressed')
master.after(clkdel, keyct.press(keyprsd.get()))
lf7.stop()
完整代码:
import tkinter as tk
from pynput.keyboard import Key, Listener
from pynput.mouse import Button, Controller
from pynput import keyboard
import pyautogui
class GUI:
def __init__(self, master):
#Defining variables
hold = tk.IntVar()
keyprsd = tk.StringVar()
self.run = False
msbt = tk.IntVar()
mousect = Controller()
keyct = Controller()
#Creating main window
master = master
master.title('Key Clicker')
master.geometry('250x250')
master.resizable(False, False)
#Creating radio buttons:
#Autoclick button
self.autoclick = tk.Radiobutton(master, text='Autoclick', variable=hold, value=1)
self.autoclick.grid(row=0, column=0, sticky='en', padx=30, pady=5)
#Hold button
self.holdbt = tk.Radiobutton(master, text='Hold', variable=hold, value=2)
self.holdbt.grid(row=0, column=1, sticky='wn', padx=0, pady=5)
#Creating keyboard button label
self.kbtlabel = tk.Label(master, textvariable=keyprsd, width=10, bg='Light Blue')
self.kbtlabel.grid(row=1, column=0, sticky='wens')
#Creating keyboard button detection:
#Functions to detect key to be pressed
def lforsetkey():
lst = Listener(on_press=ksetcall)
lst.start()
def ksetcall(key):
print('{} was pressed'.format(key))
keyprsd.set(key)
return False
#Functions to detect when to start and stop autoclicking/holding
def f7press(key):
print('{} was pressed'.format(key))
if key == keyboard.Key.f7:
self.run = False
if key == keyboard.Key.f6:
self.run = True
stmouse()
if key == keyboard.Key.f8:
self.run = True
stkey()
def lforf7():
global lf7
lf7 = Listener(on_press=f7press)
lf7.start()
lforf7()
#Creating key selection button
self.kbtsel = tk.Button(master, text='Click and press a key', command=lforsetkey)
self.kbtsel.grid(row=2, column=0, sticky='wen', padx=0)
#Creating list for mouse buttons
self.mslft = tk.Radiobutton(master, text='Left Click', variable=msbt, value=1)
self.mslft.grid(row=1, column=1, sticky='en', padx=10)
self.msrft = tk.Radiobutton(master, text='Right Click', variable=msbt, value=2)
self.msrft.grid(row=2, column=1, sticky='en', padx=10)
#Creating autoclick frequency label
self.clklb = tk.Label(master, text='Autoclick frequency (ms)')
self.clklb.grid(row=3, column=0)
#Creating autoclick frequency entry
self.clkent = tk.Entry(master)
self.clkent.grid(row=3, column=1)
#Creating mouse autoclick button
def stmouse():
self.run = True
lforf7()
try:
clkdel = int(self.clkent.get())
except ValueError:
print('Value Error')
#Autoclicking left button
if int(msbt.get()) == 1 and int(hold.get()) == 1:
print('Starting mouse autoclick...')
while self.run == True:
print('Clicked')
master.after(clkdel, mousect.click(Button.left))
lf7.stop()
#Autoclicking right button
elif int(msbt.get()) == 2 and int(hold.get()) == 1:
print('Starting mouse autoclick...')
while self.run == True:
print('Clicked')
master.after(clkdel, mousect.click(Button.right))
lf7.stop()
#Holding left button
elif int(msbt.get()) == 1 and int(hold.get()) == 2:
print('Starting mouse holding...')
while self.run == True:
pyautogui.mouseDown(button='left')
lf7.stop()
pyautogui.mouseUp(button='left')
#Holding right button
elif int(msbt.get()) == 2 and int(hold.get()) == 2:
print('Starting mouse holding...')
while self.run == True:
pyautogui.mouseDown(button='right')
lf7.stop()
pyautogui.mouseUp(button='right')
else:
print('Error')
self.msbt = tk.Button(master, text='Click to start holding/autoclicking mouse', command=stmouse)
self.msbt.grid(row=4, column=0, columnspan=2, sticky='swe', pady=5)
#Creating keyboard button
def stkey():
#Setting up variables and starting listener
self.run = True
lforf7()
try:
clkdel = int(self.clkent.get())
except ValueError:
print('Value Error')
#Autoclicking keyboard key (using pynput) (not working)
#hold = whether to autoclick or hold key
#clkdel = delay between keyboard presses
#keyprsd = key to be pressed (tk.StringVar)
#lf7 = listener for when to start/stop
if int(hold.get()) == 1:
print('Starting keyboard pressing...')
while self.run == True:
print('Pressed')
master.after(clkdel, keyct.press(keyprsd.get()))
lf7.stop()
#Holding keyboard key (also not working)
elif int(hold.get()) == 2:
print('Holding keyboard...')
while self.run == True:
pyautogui.keyDown(keyprsd.get())
lf7.stop()
print('Stopping')
pyautogui.keyUp(keyprsd.get())
else:
print('Error')
self.kbt = tk.Button(master, text='Click to start holding/autoclicking keyboard', command=stkey)
self.kbt.grid(row=5, column=0, columnspan=2, sticky='swe', pady=5)
root = tk.Tk()
GUI(root)
root.mainloop()
你的主要问题是你只导入了鼠标控制器
from pynput.mouse import Button, Controller
你用它来做鼠标和键盘
mousect = Controller()
keyct = Controller()
但是他们有不同的控制器,它们的工作方式不同。
键盘控制器可以获取字符串,但鼠标控制器需要带有 .value
你应该使用 differenet 控制器
from pynput import mouse
from pynput import keyboard
mousect = mouse.Controller()
keyct = keyboard.Controller()
这解决了主要问题。
但还有其他问题 - after()
(类似于 command=
和 bind()
)需要没有参数的函数名称,您可以使用 lambda
(如 command=
或 bind()
) 或者你必须在函数名后使用参数
master.after(clkdel, keyct.press, keyprsd.get())
master.after(clkdel, mousect.click, Button.left)
master.after(clkdel, mousect.click, Button.right)
顺便说一句: 另一个问题是您的代码不可读。您应该将嵌套函数移到 class 之外或创建 class 方法,这样您就不需要 global
而需要 self.
。您还可以使用更具可读性的名称 - 即。 key_controller
比 keyct
.
参见:PEP 8 -- Style Guide for Python Code
编辑:
Listener
为特殊对象提供有关密钥的信息,然后将其作为字符串放入 StringVar
中,稍后您从 StringVar
中获取它作为字符串并在 [=30 中使用该字符串=] - 它可以用于普通键但不适用于特殊键。
您必须保留原始对象并在 press()
中将此对象用于所有键(普通键和特殊键)。即
def ksetcall(key):
self.key = key # keep original object
print('{} was pressed'.format(key))
keyprsd.set(key)
return False
以后
keyct.press(self.key)
而不是keyct.press(keyprsd.get())