Как мне правильно запустить поток с ткинтером?
У меня есть такой код:
Длинный код
from tkinter import * from tkinter import ttk import re import win32gui import threading from threading import Timer import traceback import configparser import pyautogui import cv2 import keyboard import time import queue try: def read_config(name): config = configparser.ConfigParser() config.read(name, encoding='utf-8') conf = {} conf['scale_x'] = config.get("Combinations", "scale_x") conf['scale_y'] = config.get("Combinations", "scale_y") conf['resolution'] = config.get("Combinations", "Resolution") return conf conf = read_config("code/buttons.ini") resolution = conf['resolution'] resolutionObject = { '0': [1034,436,329,329,329,329], #1366x768 #[x,y,w,h,size,sizeReal] '1': [1054,514,384,384,384,384], #1440x900 '2': [1234,604,444,444,444,444], #1680x1050 '3': [1462,622,456,456,456,456], #1920x1080 '4': [1462,742,456,456,456,456], #1920x1200 #'3': [1034,436,329,329,329,329], #2560x1080 '5': [1955,835,605,605,465,605], #2560x1440 '6': [2835,835,605,605,465,605], #3440x1440 '7': [2940,1260,900,900,480,900], #3840x2160 '8': [3924,1684,1196,1196,460,1196], #5120x2280 } resolutionX = resolutionObject[resolution][0] resolutionY = resolutionObject[resolution][1] resolutionW = resolutionObject[resolution][2] resolutionH = resolutionObject[resolution][3] def process_selection(selection): # Код убран для экономии времени читателя вопроса ###################################################################### #Создание окна масштаба file = open('code/scale.txt', 'r') scale = file.read() file.close() if scale == "" or scale == "0": scale = "5" file = open('code/scale.txt', 'w') file.write(scale) file.close() scale = round(float(scale), 1) def close(): # Код убран для экономии времени читателя вопроса def validation(newval): # Код убран для экономии времени читателя вопроса def selectWindow(event=1): # Код убран для экономии времени читателя вопроса def window(): def set_transparency(root_window, transparency, fast=False): if transparency == 1.0: root_window.attributes('-alpha', transparency) else: if fast: root_window.attributes('-alpha', transparency) else: time.sleep(1.5) root_window.attributes('-alpha', transparency) def update_window(root_window, label_text, selection_label): try: data = state_queue.get_nowait() if data.get("labeltext") is not None: label_text["text"] = data.get("labeltext") elif data.get("set_transparency") is not None: if root_window.attributes('-alpha') == 0.0 and data.get("set_transparency") == 1.0: print("Setting transparency 1") set_transparency(root_window, data.get("set_transparency")) elif root_window.attributes('-alpha') == 1.0 and data.get("set_transparency") == 0.0: print("Setting transparency 2") set_transparency(root_window, data.get("set_transparency")) else: print("Setting transparency 3") elif data.get("selection") is not None: selection_label["text"] = data.get("selection") else: print("Ошибка. Неверные данные.") except queue.Empty: pass root_window.after(10, lambda: update_window(root_window, label_text, selection_label)) root = Tk() geometry = f"199x70+{conf['scale_x']}+{conf['scale_y']}" root.geometry(geometry) # check = (root.register(validation), "%P") # entry = Entry(fg="yellow", bg="black", font=('Roboto', '16'), width=5, validate="key", validatecommand=check) # entry.master.overrideredirect(True) # entry.master.lift() # entry.master.wm_attributes("-topmost", True) # entry.place(x=22, y=38) label = Label(root, text=f'{scale} пикс/м', font=('Roboto', '19'), fg='yellow', bg='brown') label.master.overrideredirect(True) label.master.lift() label.master.wm_attributes("-topmost", True) label.pack(side=TOP) selection = Label(root, text="Ожидаю ввода", font=('Roboto', '19'), fg='yellow', bg='brown') selection.master.overrideredirect(True) selection.master.lift() selection.master.wm_attributes("-topmost", True) selection.pack(side=BOTTOM) #set_transparency(root, 0.0, True) btn1 = ttk.Button(text="X", command=lambda: quit(), width=3) btn1.master.overrideredirect(True) btn1.master.lift() btn1.master.wm_attributes("-topmost", True) btn1.place(x=169, y=3) timeout = 0 t = Timer(timeout, selectWindow) t.start() root.lift() root.focus_force() root.after(10, lambda: update_window(root, label, selection)) root.mainloop() def main(): elements = [140, 150, 160, 170, 180, 185, 190, 200, 225, 250, 275, 300, 325, 350, 400, 450, 500, 550] current_selection = -1 n_seconds = 2 # Время бездействия в секундах plus = 'ctrl+=' # Комбинация клавиш для выбора элемента minus = 'ctrl+-' t = None win = None def on_key_event(event): nonlocal current_selection nonlocal t nonlocal win global Window if event.event_type == keyboard.KEY_DOWN: if keyboard.is_pressed(plus): #check_window() data = {"set_transparency": 1.0} state_queue.put(data) current_selection += 1 current_selection %= len(elements) # Зацикливание списка print(f"Current selection: {elements[current_selection]}") selection_data = {"selection": elements[current_selection]} state_queue.put(selection_data) if t is not None: t.cancel() t = Timer(n_seconds, process_selection, [elements[current_selection]]) t.start() else: t = Timer(n_seconds, process_selection, [elements[current_selection]]) t.start() elif keyboard.is_pressed(minus): #check_window() data = {"set_transparency": 1.0} state_queue.put(data) current_selection -= 1 current_selection %= len(elements) # Зацикливание списка print(f"Current selection: {elements[current_selection]}") selection_data = {"selection": elements[current_selection]} state_queue.put(selection_data) if t is not None: t.cancel() t = Timer(n_seconds, process_selection, [elements[current_selection]]) t.start() else: t = Timer(n_seconds, process_selection, [elements[current_selection]]) t.start() keyboard.on_press(on_key_event) while True: time.sleep(0.01) ###################################################################### if __name__ == "__main__": state_queue = queue.Queue() Window = threading.Thread(target=window) Window.start() main() except Exception as e: file = open('error.log', 'a') file.write('nn') traceback.print_exc(file=file, chain=True) traceback.print_exc() file.close() |
from tkinter import * from tkinter import ttk import re import win32gui import threading from threading import Timer import traceback import configparser import pyautogui import cv2 import keyboard import time import queue try: def read_config(name): config = configparser.ConfigParser() config.read(name, encoding='utf-8') conf = {} conf['scale_x'] = config.get("Combinations", "scale_x") conf['scale_y'] = config.get("Combinations", "scale_y") conf['resolution'] = config.get("Combinations", "Resolution") return conf conf = read_config("code/buttons.ini") resolution = conf['resolution'] resolutionObject = { '0': [1034,436,329,329,329,329], #1366x768 #[x,y,w,h,size,sizeReal] '1': [1054,514,384,384,384,384], #1440x900 '2': [1234,604,444,444,444,444], #1680x1050 '3': [1462,622,456,456,456,456], #1920x1080 '4': [1462,742,456,456,456,456], #1920x1200 #'3': [1034,436,329,329,329,329], #2560x1080 '5': [1955,835,605,605,465,605], #2560x1440 '6': [2835,835,605,605,465,605], #3440x1440 '7': [2940,1260,900,900,480,900], #3840x2160 '8': [3924,1684,1196,1196,460,1196], #5120x2280 } resolutionX = resolutionObject[resolution][0] resolutionY = resolutionObject[resolution][1] resolutionW = resolutionObject[resolution][2] resolutionH = resolutionObject[resolution][3] def process_selection(selection): # Код убран для экономии времени читателя вопроса ###################################################################### #Создание окна масштаба file = open('code/scale.txt', 'r') scale = file.read() file.close() if scale == "" or scale == "0": scale = "5" file = open('code/scale.txt', 'w') file.write(scale) file.close() scale = round(float(scale), 1) def close(): # Код убран для экономии времени читателя вопроса def validation(newval): # Код убран для экономии времени читателя вопроса def selectWindow(event=1): # Код убран для экономии времени читателя вопроса def window(): def set_transparency(root_window, transparency, fast=False): if transparency == 1.0: root_window.attributes('-alpha', transparency) else: if fast: root_window.attributes('-alpha', transparency) else: time.sleep(1.5) root_window.attributes('-alpha', transparency) def update_window(root_window, label_text, selection_label): try: data = state_queue.get_nowait() if data.get("labeltext") is not None: label_text["text"] = data.get("labeltext") elif data.get("set_transparency") is not None: if root_window.attributes('-alpha') == 0.0 and data.get("set_transparency") == 1.0: print("Setting transparency 1") set_transparency(root_window, data.get("set_transparency")) elif root_window.attributes('-alpha') == 1.0 and data.get("set_transparency") == 0.0: print("Setting transparency 2") set_transparency(root_window, data.get("set_transparency")) else: print("Setting transparency 3") elif data.get("selection") is not None: selection_label["text"] = data.get("selection") else: print("Ошибка. Неверные данные.") except queue.Empty: pass root_window.after(10, lambda: update_window(root_window, label_text, selection_label)) root = Tk() geometry = f"199x70+{conf['scale_x']}+{conf['scale_y']}" root.geometry(geometry) # check = (root.register(validation), "%P") # entry = Entry(fg="yellow", bg="black", font=('Roboto', '16'), width=5, validate="key", validatecommand=check) # entry.master.overrideredirect(True) # entry.master.lift() # entry.master.wm_attributes("-topmost", True) # entry.place(x=22, y=38) label = Label(root, text=f'{scale} пикс/м', font=('Roboto', '19'), fg='yellow', bg='brown') label.master.overrideredirect(True) label.master.lift() label.master.wm_attributes("-topmost", True) label.pack(side=TOP) selection = Label(root, text="Ожидаю ввода", font=('Roboto', '19'), fg='yellow', bg='brown') selection.master.overrideredirect(True) selection.master.lift() selection.master.wm_attributes("-topmost", True) selection.pack(side=BOTTOM) #set_transparency(root, 0.0, True) btn1 = ttk.Button(text="X", command=lambda: quit(), width=3) btn1.master.overrideredirect(True) btn1.master.lift() btn1.master.wm_attributes("-topmost", True) btn1.place(x=169, y=3) timeout = 0 t = Timer(timeout, selectWindow) t.start() root.lift() root.focus_force() root.after(10, lambda: update_window(root, label, selection)) root.mainloop() def main(): elements = [140, 150, 160, 170, 180, 185, 190, 200, 225, 250, 275, 300, 325, 350, 400, 450, 500, 550] current_selection = -1 n_seconds = 2 # Время бездействия в секундах plus = 'ctrl+=' # Комбинация клавиш для выбора элемента minus = 'ctrl+-' t = None win = None def on_key_event(event): nonlocal current_selection nonlocal t nonlocal win global Window if event.event_type == keyboard.KEY_DOWN: if keyboard.is_pressed(plus): #check_window() data = {"set_transparency": 1.0} state_queue.put(data) current_selection += 1 current_selection %= len(elements) # Зацикливание списка print(f"Current selection: {elements[current_selection]}") selection_data = {"selection": elements[current_selection]} state_queue.put(selection_data) if t is not None: t.cancel() t = Timer(n_seconds, process_selection, [elements[current_selection]]) t.start() else: t = Timer(n_seconds, process_selection, [elements[current_selection]]) t.start() elif keyboard.is_pressed(minus): #check_window() data = {"set_transparency": 1.0} state_queue.put(data) current_selection -= 1 current_selection %= len(elements) # Зацикливание списка print(f"Current selection: {elements[current_selection]}") selection_data = {"selection": elements[current_selection]} state_queue.put(selection_data) if t is not None: t.cancel() t = Timer(n_seconds, process_selection, [elements[current_selection]]) t.start() else: t = Timer(n_seconds, process_selection, [elements[current_selection]]) t.start() keyboard.on_press(on_key_event) while True: time.sleep(0.01) ###################################################################### if __name__ == "__main__": state_queue = queue.Queue() Window = threading.Thread(target=window) Window.start() main() except Exception as e: file = open('error.log', 'a') file.write('nn') traceback.print_exc(file=file, chain=True) traceback.print_exc() file.close()
Я хочу сделать так: я(код) или пользователь завершаем работу потока, закрывая окно, но если пользователь снова нажимает комбинацию клавиш, то поток проверяется на мёртв/жив, и если мертв, то есть окно закрыто, то он запускался снова и запускал окно. Если есть более адекватный способ, буду рад послушать. Сейчас у меня сделано костыльно - окно становится прозрачным, но не закрывается. Это может быть не очень удобно.
Дополнительно:
root.withdraw() для скрытия и root.deiconify() для показа пробовал?
- Нет. Я их упоминания нигде не видел, пока искал. Спасибо, помогло!
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Для запуска потока с ткинтером в PHP вам нужно использовать класс \Thread из расширения pthreads. Вот пример кода, демонстрирующий это:
synchronized(function($tk) { $tk->wait(); }, $tk); } } $thread = new MyThread(); $thread->start(); $thread->synchronized(function($thread) { $thread->notify(); }, $thread); $thread->join(); ?>
В этом примере создается класс MyThread, который наследуется от класса Thread. В методе run() создается объект Threaded (ткинтер) и блокируется его с использованием метода synchronized. Затем создается объект потока, запускается и блокируется с использованием методов synchronized и notify. После этого поток присоединяется с использованием метода join().
Убедитесь, что у вас установлено и включено расширение pthreads для PHP, иначе этот код не будет работать. Не забудьте также проверить совместимость версий PHP и pthreads.
Надеюсь, этот ответ поможет вам правильно запустить поток с ткинтером в PHP. Если у вас возникнут дополнительные вопросы, не стесняйтесь задавать их.