【问题标题】:Refreshing Tkinter root window for Multiplication Table刷新乘法表的 Tkinter 根窗口
【发布时间】:2020-11-08 06:15:41
【问题描述】:

我是 Python 新手,并试图在 Python 3.8 中创建一个乘法表,使用标签数组来保存每个 Line 字符串。该代码有效,但在随后的 Button 单击时,它会将新的标签集附加到第一组标签的正下方,而不是首先清除它。

from tkinter import *
root = Tk()
sizex = 600; sizey = 400; posx  = 0; posy  = 0
root.wm_geometry("%dx%d+%d+%d" % (sizex, sizey, posx, posy))

labels = []  # creates an empty list for your labels
def showTable():
    del labels[:] # delete any previous labels from window --> doesn't work?
    nums = range(10)
    tbl = entry.get()

    for i in nums:  # iterates over your nums
        txt = tbl + ' x ' + str(i + 1) + ' = ' + str(int(tbl) * (i + 1))
        label = Label(root, text = txt, bg = 'cyan')  # set your text and random bgcolor --> how to randomize color?
#       label.place(x = 10, y = 10 + (30 + i))
        label.pack()
        labels.append(label)  # appends the label to the list for further use

entry = Entry(root)
entry.place(x = 50,y = 50) # doesn't place the textbox at given positions?
entry.pack()

btn = Button(root, text = 'Show Table', command = showTable)
btn.place(x = 100, y = 100) # doesn't place the button at given positions?
btn.pack()

root.mainloop()

我在我认为代码不起作用的地方添加了 cmets。在纠正和优化此代码时,任何帮助将不胜感激。另外,有没有办法随机化每行的背景颜色?

【问题讨论】:

  • 您可以重复使用标签:预先创建标签,然后修改其内容,例如label[i]['text] = "({} x {} = {}).format(arg1,arg2,arg3)"。如果您仍然想销毁一个小部件(可能是次优方法)迭代每个标签小部件并执行.destroy()。此外,您可以“隐藏”小部件(由pack 几何经理制作)做label[i].pack_forget()
  • @Space 你能把它作为答案发布吗?
  • anwser 已被接受,只是一个更正:要修改小部件的“属性”,请使用label[i]["text"] = "({} x {} = {})".format(arg1,arg2,arg3)label[i].configure(text="({} x {} = {})".format(arg1,arg2,arg3))。此外,我强烈建议您重复使用标签,而不是在每次迭代时销毁并重新创建它们。
  • @Space 重复使用是对的。我同意。我可以用重复使用标签的代码来补充我的答案吗?
  • @sifar 我补充了我的答案。

标签: python python-3.x for-loop tkinter


【解决方案1】:

您只需从label 列表中删除标签。它们仍然存在。您需要使用destroy 方法从其容器中删除一个小部件。此外,C 样式格式 (%) 在今天几乎已经过时,str.format 或 f 字符串要好得多。

您还可以将所有标签放入Frame 对象中,然后仅销毁该Frame。在这种情况下,您不必为标签使用集合。并且可能如果某些值只使用一次,则没有必要为它们创建变量。当然不是这样,当一个值取自一些复杂的表达式或者你需要通过它的名字来阐明它的含义时。

同样只有一种包装元素的方法可以用于窗口。您不能使用一种方法,然后使用另一种方法。 IE。您选择packgridplace,然后仅使用该选定方法。如果你想将小部件放在顶部中心,pack 默认会这样做,它比place 更方便使用。 packside 参数用于选择打包方向,padypadx 参数用于选择外部填充。

entry 变量名不是一个好方法,因为它没有提供有关将在那里输入哪些数据的信息。

对于随机颜色,您可以使用random.choice 函数。

这是您的代码以及我的更改:

from tkinter import *
import random

root = Tk()
sizex = 600;
sizey = 400;
posx  = 0;
posy  = 0
root.wm_geometry('{}x{}+{}+{}'.format(sizex, sizey, posx, posy))
main_outer_pady = 4
bg_colors = 'red', 'yellow', 'blue', 'green', 'gray'

labels = []  # creates an empty list for your labels
def showTable():
    for l in labels:
        l.destroy()
    labels.clear()

    entered_num = num_to_multiply_entry.get()
    for i in range(10):  # iterates over your nums
        txt = f'{entered_num} x {str(i + 1)} = {int(entered_num) * (i + 1)}'
        # Here we randomize background color. We can
        # randomize foreground color with the same way.
        label = Label(root, text=txt, bg=random.choice(bg_colors))

        label.pack(pady=main_outer_pady)
        labels.append(label)  # appends the label to the list for further use

num_to_multiply_entry = Entry(root)
num_to_multiply_entry.pack(pady=main_outer_pady)

btn = Button(root, text='Show Table', command=showTable)
btn.pack(pady=main_outer_pady)

root.mainloop()

编辑:

标签复用示例:

from tkinter import *
from random import choice


sizex = 600
sizey = 400
posx = 0
posy = 0
main_outer_pady = 4
bg_colors = 'red', 'yellow', 'blue', 'green', 'gray'
labels = []

def update_table():
    entered_num = num_to_multiply_entry.get()
    # Iterates over your nums.
    for i in range(1, 11):
        txt = f'{entered_num} x {i} = {int(entered_num) * i}'
        # Here we randomize background color. We can
        # randomize foreground color with the same way.
        labels[i-1].configure(text=txt, bg=choice(bg_colors))

root = Tk()
root.wm_geometry('{}x{}+{}+{}'.format(sizex, sizey, posx, posy))

num_to_multiply_entry = Entry(root)
num_to_multiply_entry.pack(pady=main_outer_pady)
make_table_btn = Button(root, text='Show Table', command=update_table)
make_table_btn.pack(pady=main_outer_pady)

for i in range(10):
    labels.append(Label(root))
    labels[-1].pack(pady=main_outer_pady)

root.mainloop()

【讨论】:

  • 感谢@Splitter。这很有效,再次感谢您对我的其他查询的明确解释。
  • 我认为您正在使用一种艰难的方式来实现这一目标,销毁这些小部件,清除列表,再次打包它们,将它们附加到列表中.....
  • @Kevin Mayo 破坏的方法不是我的。我不想在编写原始代码时完全更改它。顺便说一句,现在我编写了另一个代码,其中包含重用的小部件。我同意破坏不是一个好方法。
【解决方案2】:

del labels[:] 可以正常工作,但不会更新窗口的小部件。 为了效率,我建议你先把它们放在你的窗口上,然后更新文本和“bg”。

from tkinter import *

root = Tk()
sizex = 600;
sizey = 400;
posx = 0;
posy = 0
root.wm_geometry("%dx%d+%d+%d" % (sizex, sizey, posx, posy))

def showTable():
    tbl = entry.get()
    # change the text and "bg" instead of create them again.
    for i, widget in enumerate(labels):
        txt = tbl + ' x ' + str(i + 1) + ' = ' + str(int(tbl) * (i + 1))
        widget.config(text=txt)
        widget.config(bg='cyan')

entry = Entry(root)
entry.place(x=50, y=50)  # doesn't place the textbox at given positions?
entry.pack()

btn = Button(root, text='Show Table', command=showTable)
btn.place(x=100, y=100)  # doesn't place the button at given positions?
btn.pack()

nums = range(10)

# save them in a list, and use pack layout manager to put them on your window.
labels = [label.pack() or label for i in nums for label in [Label(root)]]

root.mainloop()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-27
    • 2010-12-29
    • 1970-01-01
    • 2020-04-14
    • 2020-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多