#python #multithreading #python-3.9
Вопрос:
Я пытаюсь создать программное обеспечение для сопоставления клавиш, в нем есть кнопка, которая активирует сопоставление клавиш, которое в основном запускает поток, вызывающий функцию, у которой есть условный цикл, проверяющий нажатия клавиш. Но проблема в том, что даже если я устанавливаю глобальную переменную в значение false с помощью кнопки, поток не прекращается, пока я не нажму клавишу на клавиатуре.
вот мой код…. есть какие-нибудь предложения?????
Функция сопоставления Клавиш
def keymapping():
tree.bind('<Return>',func=lambda event=None:())
global active
global keymapping_running
global x_cor
global y_cor
global start_range
global end_range
global selected
global selected_iid
global keymap_name
keymapping_running = True
while active:
key = str(keyboard.read_key()).capitalize()
x = int(str(mouse.get_position()).split('(')[1].split(',')[0])
y = int(str(mouse.get_position()).split(')')[0].split(', ')[1])
for i in saves[start_range 1:end_range 1]:
i = str(i).split(" = ")
if i[0] == key:
x_cor = int(i[1].split(',')[0])
y_cor = int(i[1].split(',')[1])
if x_cor and y_cor:
mouse.move(x_cor-x,y_cor-y,absolute=False,duration=0.01)
mouse.click('left')
x_cor = 0
y_cor = 0
else:
if keyboard.is_pressed('F9'):
button_switch()
elif keyboard.is_pressed('return'):
if keyboard.is_pressed('return'):
pass
if tree.selection() == ():
pass
else:
app.wm_attributes("-topmost", 1)
tmsg.showerror("Already running",f"'{keymap_name}' is already running.")
app.wm_attributes("-topmost", 0)
else:
pass
tree.bind('<Return>',func=lambda event=None:button_switch())
keymapping_running = False
x_cor = 0
y_cor = 0
selected = ''
selected_iid = ''
app.wm_attributes("-topmost", 1)
tmsg.showinfo("Keymapping Deactivated",f"'{keymap_name}' has been deactivated")
app.wm_attributes("-topmost", 0)
keymap_name = ''
Функция кнопки Включения/Выключения
def button_switch():
global active
global keymap_name
global selected
global selected_iid
if active:
tree.item(selected,image=close_img)
active_btn.config(image=on_img)
active_btn_lbl.config(text=' Activate Keymapping ')
active = False
else:
if (not keymapping_running):
if keymap:
selected = tree.focus()
if selected != '':
selected_iid = tree.selection()
if len(selected_iid) == 1:
try:
keymap_name = tree.item(selected,'values')[0]
for j in saves:
if str(j).split(' :- ')[0] == str(already_keymap_names[int(str(selected_iid).split(",")[0].split("'")[1])]).split(" :- ")[0]:
global start_range
start_range = saves.index(j)
global end_range
end_range = start_range int(str(saves[start_range]).split(" :- ")[1].split('(')[1].split(')')[0])
active = True
active_btn.config(image=stop_img)
tree.item(selected,image=done_img)
active_btn_lbl.config(text='Deactivate Keymapping')
th = threading.Thread(target=keymapping)
th.start()
tree.selection_remove(tree.focus())
app.wm_attributes("-topmost", 1)
tmsg.showinfo("Keymapping Activated",f"'{keymap_name}' has been activated")
app.wm_attributes("-topmost", 0)
except Exception as e:
print(e)
app.wm_attributes("-topmost", 1)
tmsg.showerror("Tampering",f"There has been tampering with the 'Saved_Keymappings.dll' and we are unable to fetch '{keymap_name}'")
app.wm_attributes("-topmost", 0)
elif len(selected_iid) == 0:
app.wm_attributes("-topmost", 1)
tmsg.showerror('Nothing selected','Please select a keymapping to activate.')
app.wm_attributes("-topmost", 0)
else:
app.wm_attributes("-topmost", 1)
tmsg.showerror("Multiple Selected","You can't run multiple Keymappings together.")
app.wm_attributes("-topmost", 0)
else:
app.wm_attributes("-topmost", 1)
tmsg.showerror('Nothing selected','Please select a keymapping to activate.')
app.wm_attributes("-topmost", 0)
else:
app.wm_attributes("-topmost", 1)
tmsg.showerror("Nothing to Activate","You have no saved keymappings to activate.nnPlaese create a new keymapping before Activating")
app.wm_attributes("-topmost", 0)
else:
app.wm_attributes("-topmost", 1)
tmsg.showerror("Already running",f"'{keymap_name}' is already running.")
app.wm_attributes("-topmost", 0)
Ответ №1:
Не сказать, что интерфейс API, который вы используете (это tkinter
?), но в большинстве кнопки-работа с GUI API-интерфейсов выполняется внутри цикла событий графического интерфейса, который вызывает обратные вызовы на ваш код, когда происходит событие, и ваш обратный вызов должен немедленно вернуться так, что событие-петля можете contintue обработки нескольких событий. Поэтому, если ваш обратный вызов содержит while
цикл, который не позволяет ему немедленно вернуться, код обработки событий API графического интерфейса заблокирован для запуска и, следовательно, не выполняет/не может выполнять задачи обработки событий, которые вы ожидаете от него.
Решение: убедитесь, что ваши обратные вызовы всегда возвращают сразу — в частности, не на неопределенный срок-длина while
петли внутри вашего обратного вызова; но государство-член-переменную(ы) в вашем классе, чтобы «запомнить», что вы находитесь в середине текущего события, так что в будущем обратных вызовов можете изучить эти члены-переменные, чтобы знать, как поступить правильно.