Состояние графического интерфейса в Python Tkinter - PullRequest
0 голосов
/ 23 октября 2019

РЕДАКТИРОВАТЬ: внесены некоторые изменения, основанные на обратной связи в комментариях.

Я пытаюсь использовать функцию statusTextF для отображения сообщения WAIT / READY в графическом интерфейсе Python.

Я определил, вначало, когда рисуется графический интерфейс.

statusText = True

, а затем вызываю следующее, когда я хочу его ждать:

statusText = False

Я вызываю statusText как глобальную переменную везде, где я ее используюи у меня есть функция statusTextF, как показано ниже:

def statusTextF():
    if statusText == True:
        statusTitle = tk.Label(root,text="READY")
        statusTitle.config(font=statusFont,bg="light green")
        statusX = 500
        statusY = 450
        statusTitle.place(x=statusX,y=statusY)
        separation = 45
    else:
        statusTitle = tk.Label(root,text="WAIT")
        statusTitle.config(font=statusFont,bg="light red")
        statusX = 500
        statusY = 450
        statusTitle.place(x=statusX,y=statusY)
        separation = 45

Я все время вижу 'READY'.

Что может быть не так?

Теперь,он ничего не отображает, а также я получаю светло-красный - неизвестная ошибка цвета.

1 Ответ

1 голос
/ 24 октября 2019

Вот демонстрация того, как сделать что-то, как вы хотите. Он не использует Queue для связи между основным потоком графического интерфейса и потоком обновления статуса, поскольку объем обмена информацией между ними минимален. Вместо этого он использует threading.Lock для управления доступом к глобальной переменной, совместно используемой ими. Обратите внимание, что он также неявно используется для защиты обновлений для separation global.

Использование queue.Queue для обмена информацией должно быть достаточно простым для реализации - если он вам нужен дляпо какой-то причине - поскольку им не нужен отдельный Lock, потому что они реализуют «всю необходимую семантику блокировки» в целом.

Примечание: я пытался (в основном) следовать PEP 8 -Руководство по стилю для кода Python , чтобы сделать его достаточно читабельным - что я настоятельно предлагаю вам прочитать (и также следовать).

import random
import time
import tkinter as tk
import tkinter.font as tkFont
import threading

class StatusUpdater(threading.Thread):
#    # Not really needed since it doesn't do anything except call superclass ctor here.
#    def __init__(self, *args, **kwargs):
#        super().__init__(*args, **kwargs)  # Initialize base class constructor.

    def run(self):
        global status_flag_lock, status_flag  # Must declare these to change their values.

        while True:
            # Randomly update status_flag.
            value = random.randint(0, 100)
            with status_flag_lock:
                status_flag = bool(value % 2)  # True if odd number.
            time.sleep(.5)  # Pause updating for a little while.


def statusTextF():
    global status_flag_lock, separation  # Must declare these to change their values.

    with status_flag_lock:
        if status_flag:
            statusTitle.config(text="READY", bg="light green")
            separation = 45
        else:
            statusTitle.config(text="WAIT", bg="pink")
            separation = 55

    root.after(250, statusTextF)  # Continue the polling.


status_flag_lock = threading.Lock()  # To control concurrent access.

root = tk.Tk()
root.geometry('600x600')

STATUS_FONT = tkFont.Font(family='Courier', size=8)
STATUS_X, STATUS_Y = 500, 450

status_flag = True
separation = 45

statusTitle = tk.Label(root, text="UNKNOWN", font=STATUS_FONT, bg="gray50")
statusTitle.place(x=STATUS_X, y=STATUS_Y)

status_updater = StatusUpdater(daemon=True)
status_updater.start()  # Start updating of status flag.
root.after(250, statusTextF)  # Start polling status every 250 millisecs.
root.mainloop()
...