2017-01-24 29 views
0

我試圖讓有複選框的3×3網格的Tkinter程序複選框的網格,我創建了這樣做的代碼是:的Python,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,因爲它的relxrely會爲我調整屏幕大小),所以我知道問題不在於製作小部件,而是放置它們。

我在做什麼錯?

殼牌輸出:

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維列表/元組'self.strCategories = [[」 Q「,」W「,」E「],[」R「,」T「,」Y「],[」U「,」I「,」O「]]'然後你就不需要'range 3)' – furas

+0

它會更具可讀性'cb = tk.Checkbutton()'和'cb.place()'和'self.chckbxCategories [...] = cb' – furas

+0

你使用Python 2嗎?然後'10/40'給出'0',而不是'0.25'。更好地使用'print'來檢查你分配給'relx','depend'等的值。 – furas

回答

2

的第一個原因是,WID獲取不出現在屏幕上是因爲它們在一個框架中,並且您從未將該框架添加到主窗口。您需要在App的實例上致電packplacegrid

與問題無關,但與良好的編碼實踐相關,您應該明確創建根窗口。更改代碼的最後幾行看起來像這樣:

root = tk.Tk() 
app = App(root) 
app.pack(fill="both", expand=True) 
app.mainloop() 

當你這樣做,你現在發現你的窗口縮小到只有幾個像素。這是因爲place不會導致包含窗口擴大以適合其子級。這是有記錄的行爲,並且爲什麼place通常不是做小部件佈局的好選擇之一。如果您正在創建窗口小部件網格,則grid是自然選擇,並且可以在窗口調整大小時輕鬆做出正確反應。

這就是說,使用place時要查看您的小部件,您需要強制包含的框架或主窗口足夠大以適應此情況。您必須計算此尺寸,這是place不是最佳選擇的另一個原因。

一旦你計算出的大小,你可以使用geometry根窗口上,迫使它必須足夠大:

root.geometry("200x200") 
+0

@BrianOakley因爲每個人都對我使用'.grid'非常堅持我會切換... –

1

我用.grid(... , sticky='news')columnconfigure(..., weight=1)得到相同的結果(我希望,因爲我無法運行您的代碼看預期的結果)。

我一直類別爲2維元組,所以我可以很容易地使用for循環和item - 沒有這一切i*3+jself.strCategories[i*3+j]

我在同一個循環中創建了IntVar()。我使用臨時文件varcb,因此它更具可讀性。

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() 

enter image description here


BTW:,如果你最好的類別爲正常的元組,那麼你可以使用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() 
+0

這是好的,但我的代碼的重點是,屏幕上會有其他東西,我想這些複選框可以根據屏幕寬度進行調整 –