簡體   English   中英

tkinter 按鈕顏色不會改變(非點擊事件)

[英]tkinter button color won't change (non-click event)

我創建了一個程序,讓一名騎士繞着棋盤移動,從一個隨機位置開始,在不觸及同一個方格的情況下觸及每個方格。 我試圖通過在騎士移動時將正方形(這是一個按鈕)的顏色更改為紅色來使用 tkinter 來顯示此動作。

棋盤由 tkinter 個按鈕組成,它們與“正方形”class 相關。程序在創建網格時設置正確的 colors,但在執行過程中不會更改它們。

這是簡化的代碼(按照指示提供)。 簡化后的代碼並不是全部代碼,只是創建棋盤並將騎士放置在隨機位置的實例。 當騎士被放置時,按鈕的顏色應該改變。

    from tkinter import *
    from tkmacosx import Button
    import random
    import sys

    WIDTH = 800
    HEIGHT = 1000
    GRID_SIZE = 8


    class Square:
        board = []
        def __init__(self, x, y, touched=False):
            self.touched = touched
            self.board_btn_object = None
            self.x = x
            self.y = y
        
    
        def create_btn_object(self, location):
            btn = Button (
                location,
                width=100,
                height=100,
                text= f"{self.x}, {self.y}", 
                bg=None
            )
            self.board_btn_object = btn

            Square.board.append(self)
    
        @property
        def is_touched(self):
            self.touched = True
            self.board_btn_object.configure(bg="red")
    
        @staticmethod
        def randomlocation():
            return random.choice(Square.board)


        def __repr__(self):
            return f"Square({self.x}, {self.y}) touched={self.touched}"


    class Knight:
        def __init__(self, x, y):
            self.x = x
            self.y = y


    def main():
        root = Tk()
        root.configure(bg='blue')
        root.geometry(f'{WIDTH}x{HEIGHT}')
        root.title("chess chaser")
        root.resizable(False, False)

        top_frame = Frame(
            root,
            bg = "red",
            width = WIDTH,
            height = height_prct(10)
        )
        top_frame.place(x=0, y=0)

        bottom_frame = Frame(
            root,
            bg="black",
            width = WIDTH,
            height = height_prct(10)
        )
        bottom_frame.place(x=0, y=height_prct(90))

        center_frame = Frame(
            root,
            bg = "green",
            width = WIDTH,
            height = height_prct(80)
        )
        center_frame.place(
            x=0,
            y=height_prct(10)
        )

        make_board(center_frame)
        top_menu(top_frame)
    
        root.mainloop()


    def height_prct(percentage):
         return (HEIGHT / 100) * percentage


    def width_prct(percentage):
        return (WIDTH / 100) * percentage

    def top_menu(top_frame):

        run = Button (
            top_frame,
            width = 100,
            height = 50,
            text=f"Run",
            command = play_game
        )
        run.place(x=30, y=10)


    def make_board(center_frame):
        for x in range(GRID_SIZE):
            for y in range(GRID_SIZE):
                b = Square(x, y)
                b.create_btn_object(center_frame)
                b.board_btn_object.grid(
                    column=x, row=y
                )
                if (x+y) %2 ==0:
                    b.board_btn_object.configure(bg="grey50")
        return


    def play_game():
        knight = place_knight()
        sys.exit("Done")


    def place_knight():
        coords = Square.randomlocation()
        coords.is_touched
        x = coords.x
        y = coords.y
        knight = Knight(x, y)
        return knight


    if __name__ == "__main__":
        main()

我試過使用 self.board_btn_object.change(bg="red") and.update and.after.... 沒有任何方法可以改變顏色。

如果我更改代碼並綁定左鍵單擊以將按鈕更改為紅色,則可以正常工作; 但是,我希望它在 KNIGHT 放置在那里時發生變化。

你只是把一切都復雜化了。 創建一個單元格 class 並在其中保留 x,y 和 iftouched 的信息。 通過這種方式,您可以輕松地將新功能添加到單元格中。 創建一個板並在其中創建一個數組。 創建單元格實例並放入該數組。 無論你做什么,你都應該在這個板子里做。 定義規則、移動功能等。GUI 應該只是這個假想板的幻覺。 當事情變得復雜時,您只需根據您的電路板更新您的用戶界面!

import tkinter as tk
import random

GRID_SIZE = 8

#this is cell which going to keep information
class cell:
    def __init__(self,x,y,IsTouched=False):
        self.x= x
        self.y = y
        self.touched = IsTouched

class board:
    def __init__(self):
        self.initializeBoard()
        self.knight = [0,0]
        self.placeKnightRandomly()
        
    def moveKnight(self,x,y):
        #if knight can move in the board, return True so that
        #we can show in the GUI.
        if(self.board[x][y].touched):
            return False
        else:
            self.knight = [x,y]
            print(f"Knight new position:{x},{y}")
            return True
    
    def initializeBoard(self):
        #This function creates board from zero.
        #if you want to reset board, simple run this function.
        self.board = []
        for row in range(GRID_SIZE):
            line = []
            for column in range(GRID_SIZE):
                line.append(cell(row,column))
            self.board.append(line)

    def placeKnightRandomly(self):
        #place knight randomly
        x = random.randint(0,7)
        y = random.randint(0,7)
        self.knight = [x,y]
        self.board[x][y].touched = True
        print("knight:",x,y)


class GUI:
    def __init__(self):
        self.mw = tk.Tk()
        self.mw.geometry("800x800")

        self.board = board()

        self.buttonFrame = tk.Frame(self.mw)
        self.buttonFrame.place(relx=0,rely=0,relheight=1,relwidth=1)

        self.updateButtons()
        self.mw.mainloop()

    def updateButtons(self):
        for child in self.buttonFrame.winfo_children():
            child.destroy()
        self.buttonsList = []
        for lines in self.board.board:
            
            buttons = []

            for column in lines:
                x = column.x
                y = column.y
                btn = tk.Button(self.buttonFrame,text=f"{x},{y}",width=12,height=5)
                if(self.board.board[x][y].touched):
                    btn.configure(bg="red")

                #lets connect a buttons to functions. Send x and y as parameters.
                btn.configure(command=lambda x = x,y=y:self.touchInto(x,y) )
                btn.grid(row=x,column=y)

                buttons.append(btn)

            self.buttonsList.append(buttons)
                
    def touchInto(self,x,y):
        #when you clicked button, this function going to run
        if(self.board.moveKnight(x,y)):
            self.board.board[x][y].touched = True
            self.buttonsList[x][y].configure(bg="red")
        else:
            print("cannot move!")



if __name__ == "__main__":
    GUI()

這是它的外觀和輸出

創建一個單元格 class 並保留您制作的變量的信息。 通過這種方式,您可以輕松地將新功能添加到單元格中。 創建一個板並在其中創建一個數組。 創建單元格實例並放入該數組。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM