Tkinter创建条目的按钮



我正在努力学习tkinter,但遇到了一个小问题。我创建了一个非常简单的窗口,顶部有2条信息:活动;时间花费;和按钮"+"在窗口的底部

from tkinter import *
root = Tk()
root.geometry("274x520+868+240")
root.minsize(120, 1)
root.maxsize(3284, 1068)
root.resizable(0, 0)
root.title("Learning")
root.configure(background="black")

def new_entry():
n = [n for n in range(30, 490, 30)]
for i in n:
e1 = Entry(root)
e2 = Entry(root)
e1.place(y=i, width=133)
e2.place(x=141, y=i, width=137)
print(e1, e2)
return e1, e2

b1 = Button(root)
b1.place(y=499, width=276)
b1.configure(text="+")
b1.configure(command=new_entry)
b1.configure(background="darkgrey")
msg1 = Message(root)
msg1.place(width=133, height=29)
msg1.configure(text="Activity:")
msg1.configure(background="darkgrey")
msg2 = Message(root)
msg2.place(x=141, width=137, height=29)
msg2.configure(text="Time Spend:")
msg2.configure(background="darkgrey")
root.mainloop()

按钮应该创建两个相邻的条目,每次点击它,但如果我点击按钮,它会创建条目一次,再次点击它不会在窗口上创建条目,但只是在我的终端中创建这个:

.!entry .!entry2
.!entry3 .!entry4
.!entry5 .!entry6
.!entry7 .!entry8 

如果我删除"返回e1,e2">语句中,所有条目都是在终端和窗口中创建的,只需单击一次按钮,而不是每次单击按钮都要创建2个2个。

如果我删除"print(e1,e2)">语句中,单击该按钮将只创建两个条目一次,并且不会在终端中显示任何内容。

新条目之间应该有一点空间,直到到达按钮的上边界(在本例中为32个条目,16行)。

谁能解释一下为什么msg1显示错误(没有居中并且被分成两行),但是msg2好吧,它们的规格是一样的?

您的代码在到达return语句时立即停止,因此您的循环永远不会超过第一次迭代。

另一方面,如果您删除了return语句,则没有任何地方可以停止您的循环,因此它会继续运行,直到创建了所有的小部件。

我采用了一种使用生成器来解决您的问题的方法,这样,而不是有一个函数new_entry(),而是有一个函数生成条目,另一个函数在调用生成器时放置条目。

我还在小部件生成时稍微简化了代码,并更改了一个拼写错误(spent而不是spend)。为了不污染您的命名空间,我还用import tkinter as tk代替了from tkinter import *

import tkinter as tk
root = tk.Tk()
root.geometry("274x520+868+240")
root.minsize(120, 1)
root.maxsize(3284, 1068)
root.resizable(0, 0)
root.title("Learning")
root.configure(background="black")

def entry_generator():
for i in range(30, 490, 30):
yield place_entry(i)

def place_entry(i):
e1 = tk.Entry(root)
e2 = tk.Entry(root)
e1.place(y=i, width=133)
e2.place(x=141, y=i, width=137)
print(e1, e2)

ne = entry_generator()
b1 = tk.Button(root, command=lambda: next(ne), text='+', background='darkgrey')
b1.place(y=499, width=276)
msg1 = tk.Label(root, text='Activity:', background='darkgrey')
msg1.place(width=133, height=29)
msg2 = tk.Label(root, text='Time Spent:', background='darkgrey')
msg2.place(x=141, width=137, height=29)
root.mainloop()
def new_entry():
n = [n for n in range(30, 490, 30)]
for i in n:
e1 = Entry(root)
e2 = Entry(root)
e1.place(y=i, width=133)
e2.place(x=141, y=i, width=137)
print(e1, e2)
return e1, e2 ```

return是问题所在。请看下面的示例代码:

def iterate():
for i in range(10):
print(i)
return i
val = iterate()
print(val)

当你运行这个命令时,它会打印:

0
0

因为,return使函数立即停止并返回一些东西。如果真的有为了返回每个值,您可以创建一个列表,将内容附加到列表中,并在之后返回该列表循环:

def iterate():
arr = []
for i in range(10):
print(i)
arr.append(i)
return arr
val = iterate()
print(val)

将打印:

0
1
2
...
10
[0, 1, 2, ... 10]

或使用yield关键字(它将返回值而不停止循环):

```python
def iterate():
for i in range(10):
print(i)
yield i
val = iterate()
print(val)
print([i for i in val])

将打印:

0
1
2
...
10
<generator object iterate at 0x7fb64e584f68> 
[0, 1, 2, 3 ... 10]

对于yield,val将是一个生成器对象,您必须再次迭代以从中获取值。但是,由于返回值在代码的任何地方都没有使用,因此您可以删除return e1, e2.

另一种方法可能是保存条目的计数,并将计数乘以Entry小部件的高度

下面是一个例子:

count = 0
def new_entry():
global count
e1 = Entry(root)
e2 = Entry(root)
count += 1
y_pos = count*e1.winfo_reqheight()
e1.place(x=0, y=y_pos*1.5, width=133) # change the multiplication factor to change the padding b/w entry
e2.place(x=141, y=y_pos*1.5, width=137) # change the multiplication factor to change the padding b/w entry
print(e1, e2)

还需要注意的是,在这样的程序中使用网格布局可能会更好。

最新更新