Tkinter - перетаскивание мыши по отключенному текстовому полю останавливает обновление ()

1

Я делаю программу, которая использует какой-то виджет, который со стороны пользователя, отображает "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, чтобы я мог обновлять другие данные в каждом кадре.

  • 0
    Возможно, вам больше повезет, если вы root.mainloop() использовать root.mainloop() как обычно и использовать root.after() для периодического обновления вашего таймера. Я не уверен, как это будет взаимодействовать с перетаскиванием в текстовом поле, и оно почти наверняка прекратится, если вы перетаскиваете само окно - если вы должны продолжать работать даже в таких ситуациях, вам нужно использовать отдельный поток или процесс.
  • 0
    @jasonharper Спасибо за комментарий - я немного не уверен относительно того, как здесь будет реализована реализация потоков, могу ли я создать класс для текстового виджета и применить к нему потоки?
Показать ещё 7 комментариев
Теги:
python-3.x
tkinter

2 ответа

3
Лучший ответ

Вам не нужно управлять циклом экземпляра 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()
  • 0
    Эй, спасибо за вашу помощь! Пожалуйста, посмотрите редактирование, которое я сделал в конце моего вопроса, объясняя, почему я использовал update ().
  • 0
    Я видел ваши изменения, и я все еще думаю, что вам не нужен цикл update() . Он будет обработан с помощью mainloop() если у вас есть проблемы с его обновлением в основном цикле, тогда может быть какая-то другая причина, поскольку она должна работать нормально.
Показать ещё 6 комментариев
2

Я не мог воспроизвести описанную проблему; однако некоторые анти-шаблоны нуждаются в исправлении в отправленном коде:

  • Используйте mainloop вместо цикла while.
  • избегайте вызова обновления, mainloop обрабатывает это для вас.
  • Используйте метод root.after для повторного вызова метода.

Я изменяю свой класс 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()
  • 1
    В основном то же самое, что и мой ответ. У меня есть один вопрос мысли. Почему time_start внутри функции print_time . Это не покажет смысл запуска программы в реальном времени.
  • 1
    Да, я смотрел на ваш ответ LOL. Хороший вопрос, time_start действительно должно быть установлено первым. здесь, есть upvote для вашей проблемы.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню