select "Route_num" from "Route TB"
root_changes_2.mainloop()
запускает основной рабочий цикл. В нём программа получает сообщения от ОС о действиях пользователя и реагирует на них. Цикл прерывается, когда закрывается основное окно (ты хранишь ссылку на него в root_changes_2).import tkinter as tk
import tkinter.messagebox as tkmb
class MainWindow(tk.Tk):
"""Главное окно программы наследуется от Tk.
Вспомогательные окна - от TopLevel.
Составные элементы управления - от Frame."""
def __init__(self):
"""Метод __init__() автоматически вызывается при создании нового экземпляра класса."""
super().__init__() # обязательно вызываем конструктор родительского класса!
# при закрытии нашего окна вызовется метод __done()
# если эта функциональность не нужна, можно убрать эту строку
self.protocol('WM_DELETE_WINDOW', self.__done)
# пример создания элементов управления
# имена, начинающиеся с __, не видны снаружи класса
# мы присваиваем не просто переменным, а полям объекта. Эти поля будут видны в других методах.
self.__entry = tk.Entry(self) # поле ввода будет вложено непосредственно в наше окно
self.__entry.pack(side=tk.TOP, fill=tk.X, expand=True)
self.__btn = tk.Button(self, text='Нажми меня', command=self.__btn_pressed) # кнопка и реакция на неё
self.__btn.pack(side=tk.TOP)
def __done(self):
"""Мы прописали вызов этого метода при закрытии окна.
Тут мы можем корректно завершить работу нашей программы, а потом подтвердить закрытие."""
self.destroy() # подтверждаем закрытие. Если этот вызов не сделать, окно не закроется. Иногда это нужно.
def __btn_pressed(self):
"""Реакция на кнопку."""
text = self.__entry.get() # мы можем обращаться к полям объекта
tkmb.showinfo(
title='Вы ввели',
message=text,
parent=self
)
if __name__ == '__main__':
# это условие выполнится, только если скрипт запущен непосредственно
# оно не выполнится, если скрипт импортируется другим скриптом
# поэтому в такое условие обычно заворачивают "тело" скрипта
wnd = MainWindow() # создаём окно
wnd.mainloop() # главный рабочий цикл
# сюда управление будет передано после закрытия окна
print('Окно закрыто, пока!')
зашитая в кнопку команда объектом энтри игнорируется
import tkinter as tk
class InputBox(tk.Frame):
def __init__(self, master, **kwargs):
# вызываем унаследованный конструктор
super().__init__(master, **kwargs)
# переменные tkinter можно связывать с элементами управления
# тогда изменение в переменной отобразится в элементе, и наоборот
# это бывает удобнее, чем дёргать элемент напрямую
# а ещё можно самим реагировать на изменения значения такой переменной
self.__value = tk.StringVar()
# наше поле ввода
self.__entry = tk.Entry(self, justify=tk.RIGHT, width=22, textvariable=self.__value)
self.__entry.pack(side=tk.RIGHT, padx=10, pady=15)
# метка с пояснением
self.__helptext = tk.Label(self, bg=self['background'], height=3, text="Введите мат. выражение:")
self.__helptext.pack(side=tk.LEFT)
def get_value(self) -> str:
"""Возвращает введённую строку."""
return self.__value.get() # метод get() позволяет прочитать значение переменной tkinter
def set_value(self, value: str) -> None:
"""Заменяет содержимое введённой строки новым."""
self.__value.set(value) # метод set() позволяет задать новое значение для переменной
def append(self, symbol: str) -> None:
"""Добавляет символ(ы) к уже введённой строке."""
self.__value.set(self.__value.get() + symbol)
if __name__ == '__main__':
root = tk.Tk()
box = InputBox(root)
box.pack(side=tk.TOP, expand=True, fill=tk.BOTH)
box.set_value('Hello')
box.append(', world!')
root.mainloop()
label1.update_idletasks()
после изменения текста, чтобы попросить tkinter перерисовать окно немедленно. from matplotlib import pyplot
plot: Plot = ... # тут твой Plot
fig: pyplot.Figure = plot.backend.fig
self.fig = self.plt.figure(figsize=parent.size)
def check_gui_queue():
try:
while True:
command = gui_queue.get_nowait() # проверяем, есть ли команда для GUI
gui_queue.task_done() # на каждый успешный вызов get() - один вызов task_done()
pass # как-то обрабатываем команду
except queue.Empty: # команды нет
root.after(100, check_gui_queue) # даём GUI поработать спокойно 100 мс
async def check_bot_queue():
while True:
try:
command = bot_queue.get_nowait() # проверяем, есть ли новая команда для бота
except queue.Empty:
await asyncio.sleep(0.1) # нет - даём другим корутинам поработать 100 мс
else:
bot_queue.task_done() # на каждый успешный вызов get() - один вызов task_done()
pass # есть - как-то её обрабатываем
_tkinter.TclError: bad option "-tittle": must be -default, -detail, -icon, -message, -parent, -title, or -type
File "c:\Users\Solo\Desktop\MAXIUMAM2035\Go_user.py", line 19, in button_click
messagebox.showinfo(tittle='Проверка', message=info_str) # Для вывода информации
^^^^^^
import threading
import tkinter
from tkinter import ttk
import time
# Этот класс описывает длительную операцию, выполняемую в потоке.
class LongRunningOperation(threading.Thread):
# если твоя операция требует аргументы, они передаются через конструктор
def __init__(self, my_argument):
super().__init__(daemon=True) # если главный поток завершился, мы тоже должны
self._my_argument = my_argument # и сохраняются в self
self._stop_flag = threading.Event() # а это - признак "Пора останавливаться"
self._progress = 0 # эта переменная отслеживает прогресс
# этот объект гарантирует, что наш и внешний потоки не будут трогать self._progress одновременно
self._progress_lock = threading.Lock()
# От threading.Thread() мы унаследуем два важных метода
# start() вызывается снаружи потока и запускает наш поток
# wait() вызывается снаружи потока и ждёт, пока наш поток не остановится
# Этот метод вызывается снаружи потока и сигнализирует об остановке
# Но остановиться поток должен будет сам
def stop(self):
self._stop_flag.set() # threading.Event безопасен для использования несколькими потоками.
# Этот метод вызывается снаружи потока и позволяет узнать прогресс длительной операции
def get_progress(self):
with self._progress_lock: # любые обращения к self._progress заворачиваются в такой блок
# вообще, для чисел Lock не требуется. Но если ты хочешь сообщать что-то большее, это надо делать.
return self._progress
# Тело этого метода будет выполняться в отдельном потоке.
# Именно этот метод реализует длительную операцию.
def run(self):
# я не знаю, что творится у тебя в коде.
# Тебе придётся адаптировать свой код под этот шаблон.
self._progress = 0
self._stop_flag.clear()
print('Operation started')
while not self._stop_flag.is_set(): # пока нам не сказали остановиться
# Тут ты выполняешь порцию своей длительной работы. Например, одну итерацию цикла.
print('Operation with my_argument =', self._my_argument)
time.sleep(0.1) # это просто для примера - ждём 0.1 секунды.
# Выше ты выполняешь порцию своей длительной работы. Например, одну итерацию цикла.
with self._progress_lock:
self._progress += 1 # наращиваем прогресс
if self._progress == 100:
# в данном случае прерываем цикл, если прогресс дошел до 100 - дело сделано
# если у тебя цикл "пока снаружи не остановят", то условие и break можно убрать
break
print('Operation stopped')
class MainWindow(tkinter.Tk): # окно приложения
def __init__(self):
super().__init__()
self._operation = None # а вот тут будет храниться экземпляр класса LongRunningOperation
self.title('Pet Clicker III')
self.geometry('600x600')
self._progress = tkinter.IntVar() # переменная для прогресса в окне
# прогрессбар подхватит эту переменную, так как мы её указали в параметрах
self._progressbar = ttk.Progressbar(self, maximum=100, variable=self._progress, mode='determinate')
self._progressbar.pack(side='top', expand=True, fill='x')
self._button = tkinter.Button(self, text='Start', command=self._start_stop) # кнопка пуск/стоп
self._button.pack(side='top', expand=True, fill='x')
self.after(500, self._check_progress) # через 500 мс надо вызвать _check_progress()
def _check_progress(self): # показывает прогерсс операции в окне, если есть что показывать
if self._operation is not None: # операция сейчас выполняется?
progress = self._operation.get_progress()
self._progress.set(progress) # задаём новое значение прогресса
if not self._operation.is_alive(): # поток уже остановился?
self._progress.set(0) # сбрасываем прогресс
self._button.config(text='Start') # переименовываем кнопку
self._operation = None # забываем про объект операции
self.after(500, self._check_progress) # ещё через 500 мс вызовем функцию снова
def _start_stop(self): # запускает или останавливает операцию
if self._operation is None: # операции нет - запускаем её
self._operation = LongRunningOperation(42) # передаём аргументы в операцию. В нашем случае my_argument = 42.
self._progress.set(0) # сбрасываем прогресс
self._button.config(text='Stop') # переименовываем кнопку
self._operation.start() # запускаем второй поток, который будет выполнять операцию
else: # операция уже запущена - останавливаем её
self._operation.stop() # даём сигнал "остановись"
self._operation.join() # ждём, пока она действительно не остановится
self._progress.set(0) # сбрасываем прогресс
self._button.config(text='Start') # переименовываем кнопку
self._operation = None # забываем про объект операции
wnd = MainWindow()
wnd.mainloop()