Измените значение метки навсегда в tkinter - PullRequest
0 голосов
/ 25 июня 2019

Я хочу отобразить динамическое число, которое постоянно изменяется (температура) на моем графическом интерфейсе. Как я могу сделать мой ярлык динамичным?

Я пытался установить другие значения, но узнал, что после вызова mainLoop программа находится в бесконечном состоянии. Я читал о функциях .after (), но я не знаю, как именно его использовать, потому что я не хочу определять новые функции. Я получил возвращаемое значение и просто хочу, чтобы оно было обновлено.

import tkinter as tk
from src import SerialPort as sp

HEIGHT = 300
WIDTH = 500

root = tk.Tk()

canvas = tk.Canvas(root, height = HEIGHT, width = WIDTH)
canvas.pack()

aktTemp = tk.Label(root, text=str(sp.read_current_Temperature())+"°C", fg="red") 
aktTemp.pack()

root.mainloop()

sp.read_current_Tempera () - он вернет вам текущую температуру, поэтому я хочу, чтобы метка обновлялась каждую секунду в зависимости от вызова этой функции.

Ответы [ 2 ]

3 голосов
/ 25 июня 2019

Итак, основная проблема с постоянным обновлением чего-либо в tkinter заключается в том, что, по крайней мере, для большинства ваших программ вы заблокированы в mainloop.

Для всех намерений и целей это в основном означает, что в вашей программе вы фактически никогда не вызываете последнюю строку, потому что Python ожидает окончания основного цикла.

Как мы правильно поняли, мы можем обойти это, воспользовавшись функцией after(). Если вы еще не знаете, как это использовать (и планируете продолжать использовать tkinter), вам обязательно нужно добавить его в свой инструментарий.


Для начала я быстро изменил вашу программу, чтобы получить значение, возвращаемое в качестве температуры. Я сделал это, чтобы продемонстрировать, как можно обновить текстовый виджет, и для этого потребовалось добавить новую функцию, которая просто возвращает случайное значение.

import tkinter as tk
import random

def read_current_Temperature():
    return random.randint(1, 100)

HEIGHT = 300
WIDTH = 500

root = tk.Tk()

canvas = tk.Canvas(root, height = HEIGHT, width = WIDTH)
canvas.pack()

aktTemp = tk.Label(root, text=str(read_current_Temperature())+"°C", fg="red") 
aktTemp.pack()

root.mainloop()

read_current_Temperature()

Теперь, как вы видите, когда мы запускаем вышеописанное, мы получаем тот же результат, что и ваша исходная программа. Температура читается (читай: генерируется случайным образом), а затем обновляется виджет, а затем. , , не намного больше.


Итак, сначала нам нужно найти, где использовать after(). Есть несколько способов, которыми мы могли бы сделать это, но самый простой способ (субъективно, в данном случае. Где это возможно, я бы посоветовал использовать вместо него class, но это потребовало бы более существенных переписываний), это добавить новую функцию, как показано ниже:

import tkinter as tk
import random

def read_current_Temperature():
    return random.randint(1, 100)

def update():
    aktTemp.config(text=str(read_current_Temperature())+"°C")
    aktTemp.after(1000, update)

HEIGHT = 300
WIDTH = 500

root = tk.Tk()

canvas = tk.Canvas(root, height = HEIGHT, width = WIDTH)
canvas.pack()

aktTemp = tk.Label(root, text=str(read_current_Temperature())+"°C", fg="red") 
aktTemp.pack()

update()

root.mainloop()

Давайте посмотрим на эту строку за строкой.


update()

Первая новая строка, которую мы нажимаем (при запуске, а не при чтении), это вызов новой функции, которую я определил, говоря о которой. , .

def update():
    aktTemp.config(text=str(read_current_Temperature())+"°C")
    aktTemp.after(1000, update)

Первая строка этой функции. , .

    aktTemp.config(text=str(read_current_Temperature())+"°C")

. , , просто говорит программе перейти и получить новую температуру и назначить ее в качестве атрибута text виджета метки aktTemp. Это строка, в которой на самом деле вносит изменения в графический интерфейс.

Эта строка, с другой стороны. , .

    aktTemp.after(1000, update)

. , , это использование after Я упоминал выше. Все, что он делает, это говорит: «Каждые 1000 мс вызывайте функцию update()», которая, как мы знаем из вышеизложенного, затем обновляет метку до новой температуры и запускает еще одну задержку в 1000 мс перед повторным вызовом.


Подробнее о after() можно прочитать здесь.

2 голосов
/ 25 июня 2019

К сожалению, чтобы сделать это правильно, вам нужно определить хотя бы одну новую функцию.Я приветствую подробное объяснение @ +1 от EthanField, но вот моя альтернативная реализация, использующая возможность Tk tracing :

import tkinter as tk
from src import SerialPort as sp

WIDTH, HEIGHT = 500, 300

def refresh_temperature(string):
    temperature.set(string.format(sp.read_current_Temperature()))
    root.after(1000, refresh_temperature, string)

root = tk.Tk()

canvas = tk.Canvas(root, height=HEIGHT, width=WIDTH)
canvas.pack()

temperature = tk.StringVar()

aktTemp = tk.Label(root, textvariable=temperature, fg="red")
aktTemp.pack()

refresh_temperature("{} °C")

root.mainloop()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...