Поднятый виджет ttk.Label не может оперативно перерисоваться?Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Поднятый виджет ttk.Label не может оперативно перерисоваться?

Сообщение Anonymous »

Вот мой минимальный репрезентативный пример (MRE) о том, как я создаю виджеты ttk.Button с изображением с помощью многопоточного подхода. Однако у меня возникла проблема. Всякий раз, когда виджет self.label поднимается, его нельзя быстро перерисовать; на короткое время появляется серое пятно, прежде чем self.label появится полностью. Запуск self.update_idletasks() (см. строку 97) не может решить эту проблему. Эту проблему можно решить только запуском self.update() (необходимо раскомментировать строку 98). Однако некоторые полагают, что использование self.update() может быть вредным. Можно ли решить эту проблему без использования self.update()? Если да, то как? Не могли бы вы также объяснить, почему возникает эта проблема? Спасибо.
Демо-версия проблемы:
[img]https://i .stack.imgur.com/j5SgF.gif[/img]

Желаемый результат:
Изображение

MRE:
Пожалуйста, сохраните любой файл .jpg, который у вас есть, в тот же каталог/папку, что и этот скрипт, и переименуйте его в testimage.jpg. Как работает этот графический интерфейс? Нажмите кнопку «Выполнить», чтобы начать многопоточность. Для повторного запуска необходимо сначала нажать кнопку «Сбросить», после чего нажать кнопку «Выполнить». НЕ НАЖИМАЙТЕ «Сброс», когда потоковая передача продолжается, и наоборот.
# Python modules
import tkinter as tk
import tkinter.ttk as ttk
import concurrent.futures as cf
import queue
import threading
from itertools import repeat
import random
from time import sleep

# External modules
from PIL import Image, ImageTk

def get_thumbnail_c(gid: str, fid: str, fpath: str, psize=(100, 100)):
# print(f"{threading.main_thread()=} {threading.current_thread()=}")
with Image.open(fpath) as img:
img.load()
img.thumbnail(psize)
return gid, fid, img

def get_thumbnails_concurrently_with_queue(
g_ids: list, f_ids: list, f_paths: list, rqueue: queue.Queue,
size: tuple):
futures = []
job_fn = get_thumbnail_c

with cf.ThreadPoolExecutor() as vp_executor:
for gid, fids, fpath in zip(g_ids, f_ids, f_paths):
for gg, ff, pp in zip(repeat(gid, len(fids)), fids,
repeat(fpath, len(fids))):
job_args = gg, ff, pp, size
futures.append(vp_executor.submit(job_fn, *job_args))
for future in cf.as_completed(futures):
rqueue.put(("thumbnail", future.result()))
futures.remove(future)
if not futures:
print(f'get_thumbnails_concurrently has completed!')
rqueue.put(("completed", ()))

class GroupNoImage(ttk.Frame):
def __init__(self, master, gid, fids):
super().__init__(master, style='gframe.TFrame')
self.bns = {}
self.imgs = {}
for i, fid in enumerate(fids):
self.bns[fid] = ttk.Button(self, text=f"{gid}-P{i}", compound="top",
style="imgbns.TButton")
self.bns[fid].grid(row=0, column=i, stick="nsew")

class App(ttk.PanedWindow):
def __init__(self, master, **options):
super().__init__(master, **options)
self.master = master
self.groups = {}
self.rqueue = queue.Queue()

self.vsf = ttk.Frame(self)
self.add(self.vsf)

self.label = ttk.Label(
self, style="label.TLabel", width=7, anchor="c", text="ttk.Label",
font=('Times', '70', ''))
self.label.place(
relx=0.5, rely=0.5, relwidth=.8, relheight=.8, anchor="center",
in_=self.vsf)
self.label.lower(self.vsf)

def create_grpsframe(self):
self.grpsframe = ttk.Frame(self.vsf, style='grpsframe.TFrame')
self.grpsframe.grid(row=0, column=0, sticky="nsew")

def run(self, event):
self.create_grpsframe()
gids = [f"G{i}" for i in range(50)]
random.seed()
fids = []
for gid in gids:
f_ids = []
total = random.randint(2,10)
for i in range(total):
f_ids.append(f"{gid}-P{i}" )
fids.append(f_ids)
fpaths = ["testimage.jpg" for i in range(len(gids))]
self.create_groups_concurrently(gids, fids, fpaths)

def reset(self, event):
self.grpsframe.destroy()
self.groups.clear()

def create_groups_concurrently(self, gids, fids, fpaths):
print(f"\ncreate_groups_concurrently")

self.label.lift(self.vsf)
# self.update_idletasks() # Can't fix self.label appearance issue
# self.update() # Fixed self.label appearance issue

for i, (gid, f_ids) in enumerate(zip(gids, fids)):
self.groups[gid] = GroupNoImage(self.grpsframe, gid, f_ids)
self.groups[gid].grid(row=i, column=0, sticky="nsew")
self.update_idletasks()
# sleep(3)
print(f"\nStart thread-queue")

jthread = threading.Thread(
target=get_thumbnails_concurrently_with_queue,
args=(gids, fids, fpaths, self.rqueue, (100,100)),
name="jobthread")
jthread.start()
self.check_rqueue()

def check_rqueue(self):
# print(f"\ndef _check_thread(self, thread, start0):")
duration = 1 # millisecond
try:
info = self.rqueue.get(block=False)
# print(f"{info=}")
except queue.Empty:
self.after(1, lambda: self.check_rqueue())
else:
match info[0]:
case "thumbnail":
gid, fid, img = info[1]
print(f"{gid=} {fid=}")
grps = self.groups
grps[gid].imgs[fid] = ImageTk.PhotoImage(img)
grps[gid].bns[fid]["image"] = grps[gid].imgs[fid]
self.update_idletasks()
self.after(duration, lambda: self.check_rqueue())
case "completed":
print(f'Completed')
self.label.lower(self.vsf)

class ButtonGroups(ttk.Frame):
def __init__(self, master, **options):
super().__init__(master, style='bnframe.TFrame', **options)
self.master = master
self.bnrun = ttk.Button(
self, text="Run", width=10, style='bnrun.TButton')
self.bnreset = ttk.Button(
self, text="Reset", width=10, style='bnreset.TButton')

self.columnconfigure(0, weight=1)
self.columnconfigure(1, weight=1)
self.bnrun.grid(row=0, column=0, sticky="nsew")
self.bnreset.grid(row=0, column=1, sticky="nsew")

if __name__ == "__main__":
root = tk.Tk()
root.geometry('1300x600')
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)

ss = ttk.Style()
ss.theme_use('default')
ss.configure(".", background="gold")
ss.configure("TPanedwindow", background="red")
ss.configure('grpsframe.TFrame', background='green')
ss.configure('gframe.TFrame', background='yellow')
ss.configure('imgbns.TButton', background='orange')
ss.configure("label.TLabel", background="cyan")
ss.configure('bnframe.TFrame', background='white')
ss.configure('bnrun.TButton', background='violet')
ss.configure('bnreset.TButton', background='green')

app = App(root)
bns = ButtonGroups(root)
app.grid(row=0, column=0, sticky="nsew")
bns.grid(row=1, column=0, sticky="nsew")

bns.bnrun.bind("", app.run)
bns.bnreset.bind("", app.reset)

root.mainloop()


Подробнее здесь: https://stackoverflow.com/questions/783 ... w-promptly
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Получение текущего определения шрифта виджета tkinter.ttk.Label
    Anonymous » » в форуме Python
    0 Ответы
    17 Просмотры
    Последнее сообщение Anonymous
  • Выражения LaTeX не отображаются должным образом в widgets.Label, когда значение Label обновляется в результате события w
    Anonymous » » в форуме Python
    0 Ответы
    26 Просмотры
    Последнее сообщение Anonymous
  • Оперативно реагировать на выравнивание содержимого и слайдера в одном и том же контейнере в строке
    Anonymous » » в форуме CSS
    0 Ответы
    16 Просмотры
    Последнее сообщение Anonymous
  • Автопрокрутка Карусель не обрезается оперативно
    Anonymous » » в форуме Html
    0 Ответы
    11 Просмотры
    Последнее сообщение Anonymous
  • Автопрокрутка Карусель не обрезается оперативно
    Anonymous » » в форуме CSS
    0 Ответы
    13 Просмотры
    Последнее сообщение Anonymous

Вернуться в «Python»