Как очистить метку tkinter в l oop и как завершить l oop при нажатии другой кнопки - PullRequest
0 голосов
/ 19 июня 2020

Я новичок в python Tkinter и пытаюсь распечатать символы из разных списков при нажатии соответствующих кнопок. После нажатия кнопки элементы из списка будут продолжать отображаться всякий раз, когда пользователь нажимает любую клавишу на клавиатуре. После нажатия клавиши Enter он должен перестать отображаться из текущего списка. 1. Холст не очищается при следующей итерации. Новая метка создается и помещается вверху старой метки. Я делюсь изображением получаемого результата.

output_image

Я знаю о методе w.delete('all'), однако после его использования мой python дает сбой. Может кто-нибудь подсказать, как я могу изменить его, чтобы полностью стереть?

Как переключиться на метод кнопки 2 при нажатии кнопки 2, когда l oop в кнопке 1 выполняется. Я использовал оператор or, но мой python вылетает. Прямо сейчас я могу выйти только после нажатия клавиши ввода. Если я нажму другую кнопку, python вылетит. Могу я узнать причину сбоя моего python?

Мой код:

import tkinter as tk
import msvcrt
import random


root= tk.Tk()
myCanvas = tk.Canvas(root, width = 500, height = 200)
myCanvas.pack()

w = tk.Canvas(root, width = 500, height = 200)
w.place(relx= 0.5, rely=0.1)



def printing_2():
    flag2=1
    name_list=['Mia Jennete Moi' , 'cara', 'juili', 'meera', 'ed']
    input1 = msvcrt.getwch()
    label2 = tk.Label(root, font=('Courier', 15))
    w.create_window(60, 40, window=label2)
    if flag1!=1 or input1!='\r':
        label2.config(text=random.choice(name_list))
        root.after(10, printing_2)

def printing_1():
    flag1=1
    name_list=['Rui Sagar' , 'Nana Kana', 'Mike', 'Bob', 'Drake']
    input1 = msvcrt.getwch()
    if flag2!=1 or input1!='\r':
        label2 = tk.Label(root, text=random.choice(name_list), font=('Courier', 15))
        w.create_window(60, 40, window=label2)
        root.after(10, printing_1)

flag1=0
flag2=0
B1 = tk.Button(root, text ="Option 1", font=('Courier', 12), command= printing_1)
myCanvas.create_window(40, 30, window=B1)
B2 = tk.Button(root, text ="Option 2", font=('Courier', 12), command= printing_2)
myCanvas.create_window(40, 80, window=B2)

root.mainloop()

1 Ответ

2 голосов
/ 20 июня 2020

Вы должны создать пустую метку в начале, а позже изменить только текст в существующей метке

 label2.config(text=random.choice(name_list))

или

 label2["text"] = random.choice(name_list))

Когда вы нажимаете кнопку, вы можете запустить функцию, которая изменяет оба значения flag1 и flag2 (один набор True и другой набор False), а затем функция запуска, которая будет запускать l oop с использованием after()

И вы должны использовать global для установки внешних переменных. Без global вы создаете локальные переменные.

Вы можете использовать более читаемые имена running_1, running_2 вместо flag1, flag2 и использовать значения True/False вместо 0/1

И вместо msvcrt вы можете использовать root.bind("<Return>", stop) для запуска функции stop(), которая установит running_1 = False и running_2 = False, чтобы остановить все l oop .s


Минимальный рабочий код

BTW: я использую 500 в after(), чтобы замедлить его и посмотреть, какие значения он отображает.

import tkinter as tk
import random

# --- functions

def printing_1():
    global running_1
    global running_2
    global name_list

    running_1 = True
    running_2 = False  # stop other list
    name_list = ['Rui Sagar' , 'Nana Kana', 'Mike', 'Bob', 'Drake']

    print("start list 1")
    update_1()

def update_1():
    if running_1:
        label["text"] = random.choice(name_list)
        root.after(500, update_1)

def printing_2():
    global running_1
    global running_2
    global name_list

    running_1 = False  # stop other list
    running_2 = True
    name_list = ['Mia Jennete Moi' , 'cara', 'juili', 'meera', 'ed']

    print("start list 2")
    update_2()

def update_2():
    if running_2:
        label["text"] = random.choice(name_list)
        root.after(500, update_2)

def stop(event):
    global running_1
    global running_2

    running_1 = False
    running_2 = False

    print('stoped')

# --- main ---

running_1 = False
running_2 = False
name_list = None

root = tk.Tk()

root.bind('<Return>', stop)

canvas = tk.Canvas(root, width=500, height=200)
canvas.pack()

w = tk.Canvas(root, width=500, height=200)
w.place(relx=0.5, rely=0.1)

label = tk.Label(root)
w.create_window(60, 40, window=label)

button1 = tk.Button(root, text="Option 1", command=printing_1)
canvas.create_window(40, 30, window=button1)

button2 = tk.Button(root, text="Option 2", command=printing_2)
canvas.create_window(40, 80, window=button2)

root.mainloop()

EDIT:

Вы также можете уменьшить, чтобы использовать только одну running и одну функцию update_label().

Я проверяю, если running равно True, тогда я не запускаю новый l oop но он будет автоматически использовать уже запущенный l oop, но с новым name_list

import tkinter as tk
import random

# --- functions

def printing_1():
    global name_list
    global running

    name_list = ['Rui Sagar' , 'Nana Kana', 'Mike', 'Bob', 'Drake']

    if not running:
        running = True
        update_label()

def printing_2():
    global name_list
    global running

    name_list = ['Mia Jennete Moi' , 'cara', 'juili', 'meera', 'ed']

    if not running:
        running = True
        update_label()

def update_label():

    if running:
        label["text"] = random.choice(name_list)
        root.after(500, update_label)

def stop(event):
    global running

    running = False

    print('stoped')

# --- main ---

name_list = None
running = False

root = tk.Tk()

root.bind('<Return>', stop)

canvas = tk.Canvas(root, width=500, height=200)
canvas.pack()

w = tk.Canvas(root, width=500, height=200)
w.place(relx=0.5, rely=0.1)

label = tk.Label(root)
w.create_window(60, 40, window=label)

button1 = tk.Button(root, text="Option 1", command=printing_1)
canvas.create_window(40, 30, window=button1)

button2 = tk.Button(root, text="Option 2", command=printing_2)
canvas.create_window(40, 80, window=button2)

root.mainloop()

EDIT:

Если вы хотите обновить метку только когда вы нажимаете клавишу, вам не нужны msvcrt и after, а только bind('<Key>', function_name)

import tkinter as tk
import random

# --- functions

def printing_1():
    """Assign new list and update label"""
    global name_list

    name_list = ['Rui Sagar' , 'Nana Kana', 'Mike', 'Bob', 'Drake']

    # set value at start
    update_label()

def printing_2():
    """Assign new list and update label"""
    global name_list

    name_list = ['Mia Jennete Moi' , 'cara', 'juili', 'meera', 'ed']

    # set value at start
    update_label()

def on_key(event):
    """Update label if list is assigned to `name_list`
       and pressed key is different then `Return`"""
    if name_list and event.keysym != 'Return':
        update_label()

def update_label():
    label["text"] = random.choice(name_list)

# --- main ---

name_list = None

root = tk.Tk()
root.bind('<Key>', on_key) # run function when pressed any key

canvas = tk.Canvas(root, width=500, height=200)
canvas.pack()

w = tk.Canvas(root, width=500, height=200)
w.place(relx=0.5, rely=0.1)

label = tk.Label(root)
w.create_window(60, 40, window=label)

button1 = tk.Button(root, text="Option 1", command=printing_1)
canvas.create_window(40, 30, window=button1)

button2 = tk.Button(root, text="Option 2", command=printing_2)
canvas.create_window(40, 80, window=button2)

root.mainloop()
...