canvas.itemconfig导致无限的事件循环

时间:2017-07-19 09:14:35

标签: python tkinter python-3.5 tkinter-canvas

我尝试在每个单元格上绘制一个带有标记的3x3板。 只有在用鼠标触摸细胞时,才会显示此标记。 这可以工作一次,两次,有时是三次 - 但事件循环会激活'无限地(总是同一个事件)......

import tkinter as tk

cellsize = 50

class Board(tk.Canvas):

    def __init__(self):

        tk.Canvas.__init__(self)

        for row in range(3):
            for column in range(3):
                ulx, uly = column*cellsize, row*cellsize
                lrx, lry = ulx+cellsize, uly+cellsize
                _cell = self.create_rectangle(ulx, uly, lrx, lry,
                                              fill='green')
                _right = self.create_rectangle(ulx+39, uly+20, lrx-1, lry-20,
                                              fill='red',
                                              state='hidden')
                self.tag_bind(_cell, '<Enter>', 
                              lambda e, r=_right: self.show_pos('on', r))
                self.tag_bind(_cell, '<Leave>', 
                              lambda e, r=_right: self.show_pos('off', r))

    def show_pos(self, onoff, right):

        print('{} {}'.format(onoff, right))
        if onoff == 'on':
            self.itemconfig(right, state='normal')
        elif onoff == 'off':
            self.itemconfig(right, state='hidden')

root = tk.Tk()
Board().grid()
root.mainloop()

也许这很适合self.itemconfigure语句,因为做其他事情(例如更新状态行)按预期工作。

有解决方法吗?

提前谢谢

马文

增加:
更确切地说:它似乎坚持“状态= ......&#34;
将itemconfig更改为&#39; fill = ...&#39;在&#39; show_pos&#39;按预期工作。 所以标题应该是
&#39; canvas.itemconfig(state =&#39; ...&#39;导致无限的事件循环&#39;

1 个答案:

答案 0 :(得分:0)

使用鼠标位置方法,您可以使用:

class BoardX(tk.Canvas):
    __cells=None
    __indicators=None
    def __init__(self):
        tk.Canvas.__init__(self)

        self.__cells=[]
        self.__indicators=[]

        self.bind('<Motion>', self.show_pos)

        for row in range(3):
            for column in range(3):
                ulx, uly = column*cellsize, row*cellsize
                lrx, lry = ulx+cellsize, uly+cellsize
                self.__cells.append(self.create_rectangle(ulx, uly, lrx, lry,
                                              fill='green', tags="cell"))
                self.__indicators.append(self.create_rectangle(ulx+39, uly+20, lrx-1, lry-20,
                                              fill='red',
                                              state='hidden', tags="indicator"))
    def show_pos(self, event):
        """ Get closest widget or widget that we are above,
            tagged "cell" and indicate it
        """

        # the loop is needed for not to run into value errors
        halo=0
        widget = self.find_closest(event.x, event.y, halo=halo)

        # edit - avoid loop!
        if not widget[0] in self.find_withtag("cell"):
            return

        index = self.__cells.index(widget[0])

        for i in range(len(self.__indicators)):
            state='hidden'
            if i == index:
                state='normal'
            self.itemconfig(self.__indicators[i], state=state)

这不会触发您在进场中绑定的事件,因此应解决您的问题。

如果您因任何原因不想采用此方法,则只能绑定enter并使用find_withtag("indicator")隐藏所有其他指标 - 方法

修改的 纠正代码示例以避免循环。