【问题标题】:The item configure method didn't work in Tkinter项目配置方法在 Tkinter 中不起作用
【发布时间】:2014-03-02 06:58:05
【问题描述】:

我尝试将 Tkinter 库用于我在 python 中的小项目。我创建了一个 500 x 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

【问题讨论】:

  • 你得到什么错误?
  • 你的代码缩进不对。

标签: python class python-2.7 graphics tkinter


【解决方案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()

【讨论】:

  • 非常感谢!我完全忘记了我可以在 Button 类中绑定事件!现在可以了!
【解决方案2】:

在这里,我查看了您的代码,对其进行了调试,并进行了一些调整。现在可以了。 只需将两个脚本保存在一个文件夹中并运行您的 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()

【讨论】:

  • 如果您描述了您为使其发挥作用所做的工作,您的答案将会更加有用。尝试逐行将您的解决方案与原始解决方案进行比较,寻找您所做的不同之处是非常困难的。请记住,作为答案编写者,您的目标是教学,而不仅仅是提供代码供某人盲目剪切和粘贴。
  • 对不起。你是对的。我对此有点陌生。我所做的是将newApp = AppFrame() 添加到上面的第二个文件中。这是因为您实际上必须创建一个类的实例才能使用它。其次,我删除了self.active and 部分和self.active = True 部分,因为它不是按钮的属性。这足以让它发挥作用。 @Bryan Oakley,我希望解释得当。
  • 感谢您的耐心等待!我忘了写 self.active 部分。这很有帮助!
猜你喜欢
  • 2021-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-28
  • 2022-01-21
  • 2021-01-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多