2016-08-24 11 views
1

Tkinterを使用して簡単なプログラムを作成しています。 xviewプロパティーが変更される度に呼び出される関数をentryに変更したい。しかし、少なくとも私が見つけることができないこのような出来事はないようです。エントリのxviewが変更されたときのイベント

<Configure>イベントは、すでに処理したサイズ変更でのみ発生しますが、実際の値が変更されたときには変更されません。ユーザーがマウスをドラッグしてエントリの終わりを確認します。

import Tkinter as Tk 
import tkFileDialog 

root = Tk.Tk() 

class RepositoryFolderFrame(Tk.Frame): 
    def __init__(self, root): 
     Tk.Frame.__init__(self, root) 
     self.build_gui() 

     self.set_entry_text("Searching...") 
     #root.after(0, self.find_repo) 

     self.prev_entry_index = len(self.entry.get()) 
     root.bind("<Configure>", self.on_entry_resize) 
     #self.entry.bind(???, self.on_entry_change) 
     #self.entry.bind("<Configure>", self.on_entry_change) 

    def on_entry_resize(self, event): 
     cur_entry_index = self.entry.xview()[1] 
     if cur_entry_index != self.prev_entry_index: 
      self.entry.xview(self.prev_entry_index) 

    def on_entry_change(self, event): 
     # This should be called when xview changes... 
     cur_entry_index = self.entry.xview()[1] 
     self.prev_entry_index = cur_entry_index 

    def set_entry_text(self, text): 
     self.entry_text.set(text) 
     self.entry.xview("end") 

    def build_gui(self): 
     label = Tk.Label(self, text = "Repository folder:") 
     label.pack(side = Tk.LEFT) 
     self.label = label 

     entry_text = Tk.StringVar() 
     self.entry_text = entry_text 

     entry = Tk.Entry(self, width = 50, textvariable = entry_text) 
     entry.configure(state = 'readonly') 
     entry.pack(side = Tk.LEFT, fill = Tk.X, expand = 1) 
     self.entry = entry 

     button = Tk.Button(self, text = "Browse...") 
     button.pack(side = Tk.LEFT) 
     self.button = button 

repo_frame = RepositoryFolderFrame(root) 
repo_frame.pack(fill = Tk.X, expand = 1) 

root.mainloop() 
+0

何が?です。 'RepositoryFolderFrame' ??? –

+0

'Tkinter.Frame'を継承するクラスです(コードで分かります)。基本的には、3つのウィジェットとそれらに関連する関数のラッパーです。 –

+0

ああ、あなたがこのクラスを作りました。しかし、なぜそれは私にエラーを与えましたか? –

答えて

1

ときは、xviewの変更通知取得するためのメカニズムはありません。ここで

コードがあります。基礎となるtclコードを変更することによってそれを行う方法がありますが、それは価値よりもはるかに難しいです。

単純な解決策は、数百ミリ秒ごとにxviewをポーリングする関数を書くことです。最新のxviewを追跡して現在のものと比較することができ、変更されている場合はバインドできるカスタムイベント(例えば:<<XviewChanged>>)を起動できます。

それはこのようになります:

class RepositoryFolderFrame(Tk.Frame): 
    def __init__(self, root): 
     ... 
     self.entry.bind("<<XviewChanged>>", self.on_entry_change) 

     # keep a cache of previous xviews. A dictionary is 
     # used in case you want to do this for more than 
     self._xview = {} 
     self.watch_xview(self.entry) 

    def watch_xview(self, widget): 
     xview = widget.xview() 
     prev_xview = self._xview.get(widget, "") 
     self._xview[widget] = xview 
     if xview != prev_xview: 
      widget.event_generate("<<XviewChanged>>") 
     widget.after(100, self.watch_xview, widget) 

あなたは、コードの周りの簡単なtryとそれを扱うことができますがあなたは、エントリウィジェットが破壊されていることをエッジケースのためにそれを変更する必要があります。文字通り何百ものエントリーウィジェットがあるかどうかを確認する必要があるかもしれませんが、これは適切に機能するはずです。

+0

それは働いています。どのようにマウスのクリック+マウスのイベントをエントリにバインドするのですか?エントリは読み取り専用ですので、私が知っておくべきxviewを移動する別の方法がありますか? –

関連する問題