2017-04-16 72 views
1

我正在使用的一個項目使用tkinter製作一個遊戲板,我從未使用過tkinter並且不確定如何完成我想要的是。如何在Tkinter中創建一個20x20的網格網格,然後更改特定網格的顏色

我用canvas.createRectangle()製作了一個20x20的正方形棋盤。但我無法改變指定作品的顏色(比方說第8行和第12列的作品)。

我需要一種方法來更改特定的瓷磚填充顏色,並且希望此功能能夠取任何座標並將顏色更改爲指定的任何顏色。

如果有比使用createRectangle更好的方法,請讓我知道!

我試圖做的是在每個矩形上設置標籤,但我無法弄清楚如何使用標籤來引用每個矩形。

這是我到目前爲止有:

#imports 
from tkinter import * 

#-------------- SET UP THE WINDOW FRAME -------------------------------- 
class launchScreen(Frame): 
    #set the initial size of the window please change width and height 
    #it uses these values to determine the window size 
    #if you are on a resolution that is not 1920x1080 

    def __init__(self, master=None, width=0.5, height=0.4): 
     Frame.__init__(self, master) 
     #pack the frame to cover the whole window 
     self.pack(side=TOP, fill=BOTH, expand=YES) 

     # get screen width and height 
     ws = self.master.winfo_screenwidth() 
     hs = self.master.winfo_screenheight() 

     w = ws*width 
     h = ws*height 
     # calculate position x, y 
     x = (ws/2) - (w/2) 
     y = (hs/2) - (h/2) 
     self.master.geometry('%dx%d+%d+%d' % (w, h, x, y)) 

     #Make the screen appear on top of everything. 
     self.master.overrideredirect(True) 
     self.lift() 
#Once it has launched do everything in Main 
if __name__ == '__main__': 
    root = Tk() 
    #set the title of the applicaton window 
    root.title('Blokus') 

#--------------------- GAME STARTED ---------------------------------------- 
    def gameStart(): 

     print("Game Started") 
     #get rid of the launch screen elemenets and show the game board 
     LaunchScrn.pack_forget() 

     #this is where the 20x20 grid is made 
     #set up the view of the game board 
     def board(view): 
      w=view.winfo_width() 
      h=view.winfo_height() 
      gridWidth = w/20 
      gridHeight = h/20 
      rowNumber = 0 
      for row in range(20): 
       columnNumber = 0 
       rowNumber = rowNumber + 1 
       for col in range(20): 
         columnNumber = columnNumber + 1 
         rect = view.create_rectangle(col * gridWidth, 
         row * gridHeight, 
         (col + 1) * gridWidth, 
         (row + 1) * gridHeight, 
         fill = '#ccc') 
         #Sets row, column 
         view.itemconfig(rect, tags=(str(rowNumber), str(columnNumber))) 


     #set up the canvas for the game board grid 
     viewCanvas = Canvas(root, width=root.winfo_width(), height=root.winfo_height(),bg="#ddd") 
     viewCanvas.pack(side=TOP, fill=BOTH,padx=1,pady=1) 

     #when you click on the gameboard this event fires 
     def clickOnGameBoard(event): 
      if viewCanvas.find_withtag(CURRENT): 
       print(viewCanvas.gettags(CURRENT)) 
       print(type(viewCanvas.gettags(CURRENT))) 
       viewCanvas.itemconfig(CURRENT, fill="yellow") 
       viewCanvas.update_idletasks() 
     #bind an event when you click on the game board 
     viewCanvas.bind("<Button-1>", clickOnGameBoard) 

     #update the game board after it is done being drawn. 
     root.update_idletasks() 

     #show the gameboard in the Canvas 
     board(viewCanvas) 

     #when you click the quit button it returns you to the launch screen 
     def clickToQuit(event): 
      viewCanvas.destroy() 
      label.pack_forget() 
      LaunchScrn.pack(side=TOP, fill=BOTH, expand=YES) 

     #sets up the button for the quit 
     quitPath = "images/exit.gif" 
     quitImg = PhotoImage(file=quitPath) 
     label = Label(root, image=quitImg) 
     label.image = quitImg # you need to cache this image or it's garbage collected 
     #binds clicking this label to the quit event 
     label.bind("<Button-1>",clickToQuit) 
     label.pack(side=LEFT) 

#------------ GAME ENDED -------------------- 
    def gameEnd(): 
     #quits the game 
     def quitGame(): 
      print("Game Ended") 
      LaunchScrn.after(3000,root.destroy()) 
     quitGame() 

#---------------------------- LAUNCH SCREEN -------------------------------------------- 
    LaunchScrn = launchScreen(root) 
    LaunchScrn.config(bg="#eee") 

    b=Button(LaunchScrn, command=gameStart) 
    photo2=PhotoImage(file="images/start.gif") 
    b.config(image=photo2, width="300", height="50") 
    b.pack(side=RIGHT, fill=X, padx=10, pady=10) 

    b=Button(LaunchScrn, command=gameEnd) 
    photo4=PhotoImage(file="images/quit.gif") 
    b.config(image=photo4, width="300", height="50") 
    b.pack(side=RIGHT, fill=X, padx=10, pady=10) 

    root.mainloop() 

,展示遊戲中板:

  1. 啓動蟒蛇文件
  2. 點擊右邊按鈕(這兩個按鈕是空白)
  3. 你正在看遊戲板。

有關代碼重要信息:

  • 這是一個任務,所以我不得不刪除了很多其他的代碼,但是這應該足以說明我需要幫助解決。
  • 此GUI僅在1920x1080分辨率下正確顯示,但可通過更改寬度和高度值進行更改。 (這與問題無關,但如果您想爲自己的測試運行它會有所幫助。)
  • 我在按鈕上使用的圖像已被刪除
  • 右側的按鈕顯示了遊戲板
  • 左邊的按鈕可關閉遊戲
  • 是無法被縮放的事實是沒有問題

在此先感謝這麼多,任何人可以幫助!

+0

向我們展示您到目前爲止所嘗試的內容以及它如何偏離您的預期行爲。 –

+0

我已更新該帖子以顯示目前爲止的代碼。基本上我只需要一種方法來爲一個方塊着色而不必點擊那個特定的方塊。 – nelKorajkic

+0

您需要保存您創建的矩形的ID,以便稍後將它們傳遞給'.itemconfig()'。列表或者(行,列)元組作爲關鍵字的列表將是合理的選擇。 – jasonharper

回答

1

這裏是更新的代碼:

#imports 
from tkinter import * 

#-------------- SET UP THE WINDOW FRAME -------------------------------- 
class launchScreen(Frame): 
    #set the initial size of the window please change width and height 
    #it uses these values to determine the window size 
    #if you are on a resolution that is not 1920x1080 

    def __init__(self, master=None, width=0.5, height=0.4): 
     Frame.__init__(self, master) 
     #pack the frame to cover the whole window 
     self.pack(side=TOP, fill=BOTH, expand=YES) 

     # get screen width and height 
     ws = self.master.winfo_screenwidth() 
     hs = self.master.winfo_screenheight() 

     w = ws*width 
     h = ws*height 
     # calculate position x, y 
     x = (ws/2) - (w/2) 
     y = (hs/2) - (h/2) 
     self.master.geometry('%dx%d+%d+%d' % (w, h, x, y)) 

     #Make the screen appear on top of everything. 
     self.master.overrideredirect(True) 
     self.lift() 
#Once it has launched do everything in Main 
if __name__ == '__main__': 
    root = Tk() 
    #set the title of the applicaton window 
    root.title('Blokus') 
    coordinate={} 
    def changecolor(row, column, canvas): 
     canvas.itemconfig(coordinate[(row, column)], fill='yellow') 

#--------------------- GAME STARTED ---------------------------------------- 
    def gameStart(): 
     global coordinate 
     print("Game Started") 
     #get rid of the launch screen elemenets and show the game board 
     LaunchScrn.pack_forget() 

     #this is where the 20x20 grid is made 
     #set up the view of the game board 
     def board(view): 
      coordinate={} 
      w=view.winfo_width() 
      h=view.winfo_height() 
      gridWidth = w/20 
      gridHeight = h/20 
      rowNumber = 0 
      for row in range(20): 
       columnNumber = 0 
       rowNumber = rowNumber + 1 
       for col in range(20): 
         columnNumber = columnNumber + 1 
         rect = view.create_rectangle(col * gridWidth, 
         row * gridHeight, 
         (col + 1) * gridWidth, 
         (row + 1) * gridHeight, 
         fill = '#ccc') 
         #Sets row, column 
         view.itemconfig(rect, tags=(str(rowNumber), str(columnNumber))) 
         coordinate[(row,col)]=rect 
      return coordinate 

     #set up the canvas for the game board grid 
     viewCanvas = Canvas(root, width=root.winfo_width(), height=root.winfo_height(),bg="#ddd") 
     viewCanvas.pack(side=TOP, fill=BOTH,padx=1,pady=1) 

     #when you click on the gameboard this event fires 
     def clickOnGameBoard(event): 
      if viewCanvas.find_withtag(CURRENT): 
       print(viewCanvas.gettags(CURRENT)) 
       print(type(viewCanvas.gettags(CURRENT))) 
       viewCanvas.itemconfig(CURRENT, fill="yellow") 
       viewCanvas.update_idletasks() 
     #bind an event when you click on the game board 
     viewCanvas.bind("<Button-1>", clickOnGameBoard) 

     #update the game board after it is done being drawn. 
     root.update_idletasks() 

     #show the gameboard in the Canvas 
     coordinate=board(viewCanvas) 
     changecolor(1, 2, viewCanvas) 

     #when you click the quit button it returns you to the launch screen 
     def clickToQuit(event): 
      viewCanvas.destroy() 
      label.pack_forget() 
      LaunchScrn.pack(side=TOP, fill=BOTH, expand=YES) 

     #sets up the button for the quit 
     quitPath = "images/exit.gif" 
     quitImg = PhotoImage(file=quitPath) 
     label = Label(root, image=quitImg) 
     label.image = quitImg # you need to cache this image or it's garbage collected 
     #binds clicking this label to the quit event 
     label.bind("<Button-1>",clickToQuit) 
     label.pack(side=LEFT) 




#------------ GAME ENDED -------------------- 
    def gameEnd(): 
     #quits the game 
     def quitGame(): 
      print("Game Ended") 
      LaunchScrn.after(3000,root.destroy()) 
     quitGame() 

#---------------------------- LAUNCH SCREEN -------------------------------------------- 
    LaunchScrn = launchScreen(root) 
    LaunchScrn.config(bg="#eee") 

    b=Button(LaunchScrn,text='start', command=gameStart) 
    #photo2=PhotoImage(file="images/start.gif") 
    #b.config(image=photo2, width="300", height="50") 
    b.pack(side=RIGHT, fill=X, padx=10, pady=10) 

    b=Button(LaunchScrn, text='end',command=gameEnd) 
    #photo4=PhotoImage(file="images/quit.gif") 
    #b.config(image=photo4, width="300", height="50") 
    b.pack(side=RIGHT, fill=X, padx=10, pady=10) 

    root.mainloop() 

基本上,我定義了一個名爲changecolor功能。我還在第88行舉了一個這個函數的例子。關於訪問瓷磚的問題,我在board函數中添加了兩行,以便它將所有創建的瓷磚存儲在字典中。該字典的鍵是一個元組(row, column),從零開始。另外,因爲我沒有用於按鈕的圖片,所以我將它們更改爲文本,以便我可以運行該腳本。隨意改回他們。

+0

我認爲你需要找出一種方法在你的'gameStart'函數之外訪問你的畫布。您可以將其設爲全局變量,將其返回,或者在類中創建'gameStart'函數。 – pkqxdd

+0

這是完美的,它完全符合我的需求,並進一步進行整合,如果需要出現,我會考慮將其作爲全局變量。非常感謝! – nelKorajkic