Я делаю программу, которая использует какой-то виджет, который со стороны пользователя, отображает "uneditable" и "unselectable" строки данных.
Виджет также должен иметь полосу прокрутки, поэтому мои параметры виджетов немного ограничены из того, что я понимаю.
Кроме того, приложение постоянно обновляет номера.
Я пошел за текстовым полем - однако, когда я держу левый клик и перемещаю мышь через текстовое поле, root.update() останавливается/ждет.
Я написал несколько примеров кода, чтобы продемонстрировать это явление.
import time
from tkinter import *
class App:
def __init__(self):
self.root = Tk()
self.root.geometry("500x500")
self.root.resizable(False, False)
self.main_frame = Frame(self.root)
self.main_frame.grid(row = 0, column = 0, sticky = "news")
self.main_text_box = Text(self.main_frame)
self.main_text_box.grid(row = 0, column = 0, sticky = "news")
self.main_text_box.tag_configure("bold", font = "Helvetica 50")
self.main_text_box.insert(END, "Example text", "bold")
self.main_text_box.configure(state = DISABLED)
def update(self):
self.root.update()
def main():
application = App()
time_start = time.time()
while True:
application.update()
print("Program running, {} seconds since start".format(
round(time.time() - time_start, 3)))
if __name__ == "__main__":
main()
Когда пользователь перетаскивает мышь через текстовое поле, оператор печати в
while True:
ждет root.update().
В основном, мой вопрос: есть ли способ не иметь root.update() ждать, если мышь перетаскивается через отключенное текстовое поле?
(заметьте - я новичок на этом сайте, поэтому, если я неясен или что-то еще, пожалуйста, укажите, что я мог бы сделать лучше в моем вопросе :))
Спасибо!
Извините, я забыл упомянуть, что я использую update(), потому что в моей реальной программе (я не публиковал b/c строки 800+), у меня есть другие методы not-tkinter update() в while, чтобы я мог обновлять другие данные в каждом кадре.
Вам не нужно управлять циклом экземпляра tkinter с update()
mainloop()
сделает это за вас.
Вместо этого напишите это, когда класс наследует от Tk()
а затем сделайте часть функции print времени в классе. Мы также можем использовать after()
для обновления печати. Наконец, мы должны установить time_start для атрибута класса, который будет использоваться в нашей временной функции.
import time
import tkinter as tk
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.geometry("500x500")
self.resizable(False, False)
self.time_start = time.time()
self.main_frame = tk.Frame(self)
self.main_frame.grid(row = 0, column = 0, sticky = "news")
self.main_text_box = tk.Text(self.main_frame)
self.main_text_box.grid(row = 0, column = 0, sticky = "news")
self.main_text_box.tag_configure("bold", font = "Helvetica 50")
self.main_text_box.insert("end", "Example text", "bold")
self.main_text_box.configure(state = "disabled")
self.time_check()
def time_check(self):
print("Program running, {} seconds since start".format(round(time.time() - self.time_start, 3)))
self.after(100, self.time_check)
if __name__ == "__main__":
my_app = App()
my_app.mainloop()
update()
. Он будет обработан с помощью mainloop()
если у вас есть проблемы с его обновлением в основном цикле, тогда может быть какая-то другая причина, поскольку она должна работать нормально.
Я не мог воспроизвести описанную проблему; однако некоторые анти-шаблоны нуждаются в исправлении в отправленном коде:
Я изменяю свой класс App, чтобы он наследовал от tk.Tk
; вы можете наследовать от Frame
вместо этого; в этом случае вы должны предоставить ему мастер.
Я также разместил консольную печать в функции вне класса, так как было более целесообразно поддерживать разделение на консоль.
import time
import tkinter as tk
class App(tk.Tk):
def __init__(self):
super().__init__()
self.geometry("500x500")
self.resizable(False, False)
self.main_frame = Frame(self)
self.main_frame.grid(row = 0, column = 0, sticky = "news")
self.main_text_box = Text(self.main_frame)
self.main_text_box.grid(row = 0, column = 0, sticky = "news")
self.main_text_box.tag_configure("bold", font = "Helvetica 50")
self.main_text_box.insert(END, "Example text", "bold")
self.main_text_box.configure(state = DISABLED)
self._update_me()
def _update_me(self):
print_time()
self.after(500, self._update_me)
def print_time():
print("Program running, {} seconds since start".format(
round(time.time() - time_start, 3)))
def main():
application = App()
application.mainloop()
if __name__ == "__main__":
time_start = time.time()
main()
time_start
внутри функции print_time
. Это не покажет смысл запуска программы в реальном времени.
time_start
действительно должно быть установлено первым. здесь, есть upvote для вашей проблемы.
root.mainloop()
использоватьroot.mainloop()
как обычно и использоватьroot.after()
для периодического обновления вашего таймера. Я не уверен, как это будет взаимодействовать с перетаскиванием в текстовом поле, и оно почти наверняка прекратится, если вы перетаскиваете само окно - если вы должны продолжать работать даже в таких ситуациях, вам нужно использовать отдельный поток или процесс.