Tkinter中的item configure方法无效

0 投票
2 回答
756 浏览
提问于 2025-04-17 20:29

我尝试在我的小项目中使用Tkinter库,这个项目是用Python写的。我创建了一个500乘500的正方形,里面有10000个小正方形。

我希望每当用户点击一个小正方形时,它就变成黑色。有人能告诉我为什么吗?我会非常感激的。下面是我的图形代码:

from Tkinter import *
from button import *

class AppFrame(Frame):




def __init__(self):

    self.root = Tk()
    self.root.geometry = ("1000x1000")
    self.f = Frame(self.root, relief = 'sunken', width = 600, height = 600)
    self.w = Canvas(self.f,width = 505, height =505)

    ##get the x, y value whenever the user make a mouse click
    self.w.bind("<Button-1>", self.xy)
    self.bolist = []

    for k in range(1,101):
        for i in range(1, 101):

            button = Buttons(self.w, i * 5, k * 5, i * 5 + 5, k * 5 + 5)
            self.bolist.append(button)

    self.f.grid(column =0, columnspan = 4)
    self.w.grid(column = 0)

    self.root.mainloop()


def xy (self, event):
    self.x, self.y = event.x, event.y
    print (self.x, self.y)
    ##check each button if it's clicked
    for hb in self.bolist:
        if hb.clicked(self.x, self.y):
            print ("hurry")
            hb.activate()

还有

##button.py
from Tkinter import *


class Buttons:

def __init__(self,canvas,bx,by,tx,ty):

    self.canvas = canvas
    self.rec = canvas.create_rectangle((bx,by,tx,ty),fill = "lightgray",
                                       activefill= 'black', outline = 'lightgray')


    self.xmin = bx
    self.xmax = tx
    self.ymin = by
    self.ymax = ty
    ##print (bx, by, tx, ty)
def clicked(self, px, py):
    return (self.active and self.xmin <= px <= self.xmax and
            self.ymin <= py <= self.ymax)
def activate(self):
    self.canvas.itemconfigure(slef.rec, fill = 'black')
    self.active = True

2 个回答

1

我看了你的代码,调试了一下,并做了一些调整。现在它可以正常工作了。只要把这两个脚本放在同一个文件夹里,然后运行你的AppFrame脚本(就是这个回答中的第二个脚本)就可以了。

##button.py
from Tkinter import *

class Buttons:

    def __init__(self,canvas,bx,by,tx,ty):

        self.canvas = canvas
        self.rec = canvas.create_rectangle((bx,by,tx,ty),fill = "lightgray", activefill= 'black', outline = 'lightgray')


        self.xmin = bx
        self.xmax = tx
        self.ymin = by
        self.ymax = ty
        ##print (bx, by, tx, ty)
    def clicked(self, px, py):
        return (self.xmin <= px <= self.xmax and
                self.ymin <= py <= self.ymax)
    def activate(self):
        self.canvas.itemconfigure(self.rec, fill = 'black')

还有

from Tkinter import *
from button import *

class AppFrame(Frame):

    def __init__(self):

        self.root = Tk()
        self.root.geometry = ("1000x1000")
        self.f = Frame(self.root, relief = 'sunken', width = 600, height = 600)
        self.w = Canvas(self.f,width = 505, height =505)

        ##get the x, y value whenever the user make a mouse click
        self.w.bind("<Button-1>", self.xy)
        self.bolist = []

        for k in range(1,101):
            for i in range(1, 101):

                button = Buttons(self.w, i * 5, k * 5, i * 5 + 5, k * 5 + 5)
                self.bolist.append(button)

        self.f.grid(column =0, columnspan = 4)
        self.w.grid(column = 0)

        self.root.mainloop()


    def xy (self, event):
        self.x, self.y = event.x, event.y
        print (self.x, self.y)
        ##check each button if it's clicked
        for hb in self.bolist:
            if hb.clicked(self.x, self.y):
                print ("hurry")
                hb.activate()

newApp = AppFrame()
1

问题在于你没有初始化 active 属性,所以在单元格变为活动状态之前,它是不存在的。要解决这个问题,可以在 Buttons 类的 __init__ 方法里添加 self.active = False

你在这一行也有个拼写错误(注意你写成了 slef 而不是 self):

self.canvas.itemconfigure(slef.rec, fill = 'black')

与其在画布上使用全局绑定,不如在每个单独的矩形上设置绑定,这样会更高效。你可以利用这个绑定把 Buttons 类的实例传递给回调函数。这样你就不需要遍历几千个小部件去寻找被点击的那个了。

要做到这一点,可以使用画布的 tag_bind 方法。你可以让主程序传入一个函数的引用,当矩形被点击时就调用这个函数,然后绑定可以调用这个方法并传递对自身的引用。

例如:

class Buttons:

    def __init__(self,canvas,bx,by,tx,ty, callback):
        ...
        self.rec = canvas.create_rectangle(...)
        self.canvas.tag_bind(self.rec, "<1>", 
            lambda event: callback(self))
        ...


class AppFrame(Frame):
    def __init__(...):
        ...
            button = Buttons(..., self.callback)
        ...

    def callback(self, b):
        b.activate()

撰写回答