2017-07-19 8 views
1

私は各セルにマーカーを付けて少し3x3ボードを描こうとします。 このマーカーは、セルをマウスでタッチしたときにのみ表示されます。 これは時々、二回、一回3 3回に動作します - しかし、その後イベントループ「火災」無限(常に同じイベント)...おそらくこれは、self.itemconfigure書に貼りれcanvas.itemconfigの結果が無限のイベントループになる

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

、なぜなら他のこと(ステータス行の更新など)を行うことは、期待通りに機能します。

解決方法はありますか?具体的には
:事前に

Thxを

マーヴィン

追加=を埋める「にitemconfigを変更する状態= ...」
を」に固執するようです... show_pos 『期待どおりに動作 だから、タイトルは
でなければなりません。「『で』無限イベントループでcanvas.itemconfig(状態=』 ...」結果」

+0

"update"は状態変更後に呼び出されます(Tkinter.py、def _cnfmerge)。状態の変更により状態がさらに変化します。入力/離脱の代わりにマウス位置計算を使用してバインディングを達成しようとすると、良いことがあります。あなたの答えは – R4PH43L

答えて

0

を使用することができ、マウスの位置のアプローチを使用して:

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

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

     self.bind('&ltMotion>', 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")を使用して、すべての他のインジケータを隠すことができアプローチ -

編集 コードサンプルは、ループを回避するために修正されます。

+0

Thxです。 – Marvin

+0

あなたの以前の短いコメントに基づいて、私はfind_closestで遊んだ。私は、セルとインジケータをdictに対応するbbox値をキーとして格納しました。 「タグ」のものは私の心には来なかった。短いこと:私はあまり成功していませんでした。しかし、あなたのソリューションは、それにもかかわらず、はるかにエレガントです。時々マウスを押した後、それはwhile ..-ループで無限にくっついてしまいます。私は、より単純なソリューションを使用し、インジケータを背景色でペイントし、マウスがインジケータに入ると処理することに決めました。 – Marvin

関連する問題