我试图创建一个具有3x3网格复选框的tkinter程序,我创建的代码是:
import tkinter as tk
class App(tk.Frame):
def __init__(self,* args,** qwargs):
tk.Frame.__init__(self)
self.strCategories=("Q","W","E","R","T","Y","U","I","O")
self.varCategories={}
for x in self.strCategories:
self.varCategories[x] = tk.IntVar()
self.chckbxCategories={}
for i in range(3):
for j in range(3):
var = self.varCategories[self.strCategories[i*3+j]]
x=10/40 + 11*i/40
y=7/20 + 4*j/20
print(str(x),str(y))
checkbox = tk.Checkbutton(self, text=self.strCategories[i*3+j], font=('Lucida Grande',15),
anchor='w', bg='#FFFFFF', variable=var, onvalue=1, offvalue=0)
checkbox.place(relx=x, rely=y, relwidth=10/40, relheight=5/20)
self.chckbxCategories[self.strCategories[i*3+j]] = checkbox
app = App()
app.mainloop()
然而,小部件不会出现在屏幕上!如果我将.place
替换为其他几何管理器,则可以使用.place
,因为relx
和rely
会为我调整屏幕大小所以我知道问题不在于制作小部件而是放置它们。
我做错了什么?
Shell输出:
0.25 0.35
0.25 0.55
0.25 0.75
0.525 0.35
0.525 0.55
0.525 0.75
0.8 0.35
0.8 0.55
0.8 0.75
答案 0 :(得分:2)
小部件不会出现在屏幕上的第一个原因是因为它们位于一个框架中,而您从未将框架添加到主窗口。您需要在pack
的实例上致电place
,grid
或App
。
与问题无关但与良好编码实践相关,您应该明确创建根窗口。将代码的最后几行更改为:
root = tk.Tk()
app = App(root)
app.pack(fill="both", expand=True)
app.mainloop()
执行此操作时,您会发现窗口缩小到几个像素。这是因为place
不会导致包含窗口扩展以适合其子项。这是记录在案的行为,并且是place
通常不是做小部件布局的好选择的几个原因之一。如果要创建窗口小部件网格,grid
是自然选择,当窗口调整大小时,可以很容易地做出正确的反应。
话虽这么说,要在使用place
时看到你的小部件,你需要强制包含框架或主窗口足够大以适应这个。您必须计算此大小,这是place
不是最佳选择的另一个原因。
一旦您计算了尺寸,就可以在根窗口上使用geometry
来强制它足够大:
root.geometry("200x200")
答案 1 :(得分:1)
我使用.grid(... , sticky='news')
和columnconfigure(..., weight=1)
来获得相同的结果(我希望因为我无法运行您的代码来查看预期结果)。
我将类别保持为二维元组,因此我可以轻松使用for
循环和item
- 而不是i*3+j
和self.strCategories[i*3+j]
。
我在同一个循环中创建IntVar()
。我使用临时var
和cb
,因此它更具可读性。
import tkinter as tk
root = tk.Tk()
str_categories = ( ("Q","W","E"), ("R","T","Y"), ("U","I","O") )
var_categories = {}
chckbx_categories = {}
for r, row in enumerate(str_categories):
root.columnconfigure(r, weight=1)
root.rowconfigure(r, weight=1)
for c, item in enumerate(row):
var = tk.IntVar()
cb = tk.Checkbutton(root, text=item, variable=var, onvalue=1, offvalue=0,
font=('Lucida Grande',15), anchor='w', bg='#FFFFFF')
cb.grid(row=r, column=c, sticky='news')
var_categories[item] = var
chckbx_categories[item] = cb
root.mainloop()
顺便说一句:如果您更喜欢将类别作为普通元组,那么您可以使用range(3)
和item = str_categories[r*3+c]
,但其余部分相同。
import tkinter as tk
root = tk.Tk()
str_categories = ("Q", "W", "E", "R", "T", "Y", "U", "I", "O")
var_categories = {}
chckbx_categories = {}
for r in range(3):
root.columnconfigure(r, weight=1)
root.rowconfigure(r, weight=1)
for c in range(3):
item = str_categories[r*3+c]
var = tk.IntVar()
cb = tk.Checkbutton(root, text=item, variable=var, onvalue=1, offvalue=0,
font=('Lucida Grande',15), anchor='w', bg='#FFFFFF')
cb.grid(row=r, column=c, sticky='news')
var_categories[item] = var
chckbx_categories[item] = cb
root.mainloop()
或者您可以创建"iterator"
iterator = iter(str_categories)
然后您可以使用
获取"next"
项目
item = next(iterator)
完整版:
import tkinter as tk
root = tk.Tk()
str_categories = ("Q", "W", "E", "R", "T", "Y", "U", "I", "O")
iterator = iter(str_categories)
var_categories = {}
chckbx_categories = {}
for r in range(3):
root.columnconfigure(r, weight=1)
root.rowconfigure(r, weight=1)
for c in range(3):
item = next(iterator)
var = tk.IntVar()
cb = tk.Checkbutton(root, text=item, variable=var, onvalue=1, offvalue=0,
font=('Lucida Grande',15), anchor='w', bg='#FFFFFF')
cb.grid(row=r, column=c, sticky='news')
var_categories[item] = var
chckbx_categories[item] = cb
root.mainloop()