简体   繁体   English

项目配置方法在Tkinter中不起作用

[英]The item configure method didn't work in Tkinter

I tried to use the Tkinter library for my small project in python. 我试图在我的python小项目中使用Tkinter库。 I create a 500 by 500 square with 10000 small square in it. 我创建一个500 x 500的正方形,其中有10000个小正方形。

And I want each small square turns black when user click on it. 我希望每个小方块在用户单击时都变黑。 Can someone please tell me why, I would really appreciate it. 有人可以告诉我为什么吗,我将非常感谢。 Here is the graphics code: 这是图形代码:

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

And

##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

The problem is that you don't initialize the active attribute, so it doesn't exist until the cell becomes active. 问题在于您不初始化active属性,因此在单元格变为活动状态之前不存在该属性。 To fix that, add self.active = False inside the __init__ method of Buttons . 为了解决这个问题,添加self.active = False内部__init__的方法Buttons

You also have a typo in this line (notice you use slef rather than self ): 您在此行中也有错别字(请注意,您使用slef而不是self ):

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

Instead of a global binding on the canvas, it would be more efficient to set a binding on each individual rectangle. 代替在画布上进行全局绑定,在每个单独的矩形上设置绑定会更有效。 You can then use the binding to pass the instance of the Buttons class to the callback. 然后,您可以使用绑定将Buttons类的实例传递给回调。 This way you don't have to iterate over several thousand widgets looking for the one that was clicked on. 这样,您不必遍历数千个小部件来寻找被单击的小部件。

To do this, use the tag_bind method of the canvas. 为此,请使用画布的tag_bind方法。 You can make it so that your main program passes in a reference to a function to call when the rectangle is clicked, then the binding can call that method and pass it a reference to itself. 您可以这样做,以便您的主程序在单击矩形时传递对要调用的函数的引用,然后绑定可以调用该方法并将其传递给自身。

For example: 例如:

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

Here, I looked at your code, debugged it, and made some adjustments. 在这里,我查看了您的代码,对其进行了调试,并进行了一些调整。 It works now. 现在可以使用了。 Just keep both the scripts in one folder and run your AppFrame script (the second one in this answer) 只需将两个脚本保存在一个文件夹中,然后运行您的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')

AND

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM