Tk のほとんどのイベントと同様に、ハンドラーは、イベントが組み込みバインディングによって処理された後ではなく、処理される前に<Key>起動されます。これにより、たとえば、通常の処理が行われないようにしたり、処理内容を変更したりできます。
ただし、これは、まだ更新されていないため、新しい値にアクセスできないことを意味します ( を介してStringVar、または を呼び出すだけで)。entry.get()
を使用している場合は、「変更済み」フラグが変更された後にText発生する仮想イベントがあります。<<Modified>>そのフラグを別の目的で使用していないと仮定すると (たとえば、テキスト エディターでは、「保存ボタンを有効にする」という意味で使用したい場合があります)、それを使用して、まさに必要なことを行うことができます。
def count(self, event=None):
if not self.post_tweet.edit_modified():
return
self.post_tweet.edit_modified(False)
self.x = len(self.post_tweet.get(1.0, END))
self.char_count.set(str(140 - self.x))
# ...
self.post_tweet.bind("<<Modified>>", self.count)
通常、このようなものが必要な場合は、Entryではなく が必要ですText。これは、これを行うためのはるかに優れた方法である検証を提供します。Tkinter の基本を超えたすべてのものと同様に、Tcl/Tk ドキュメントを読まずにこれを理解する方法はありません (これが、Tkinter ドキュメントがそれらにリンクしている理由です)。実際、Tk のドキュメントでさえ検証についてはあまり詳しく説明していません。しかし、これがどのように機能するかです:
def count(self, new_text):
self.x = len(new_text)
self.char_count.set(str(140 - self.x))
return True
# ...
self.vcmd = self.master.register(self.count)
self.post_tweet = Edit(self.master, validate='key',
validatecommand=(self.vcmd, '%P'))
はvalidatecommand、関数に渡す 0 個以上の引数のリストを取ることができます。引数は、%P許可した場合にエントリが持つ新しい値を取得します。詳細についてVALIDATIONは、エントリのマンページを参照してください。
入力を拒否したい場合 (たとえば、誰かが 140 文字を超えて入力するのを実際にブロックしたい場合) はFalse、True.
ところで、Tk wikiを調べて、 ActiveStateで Tkinter レシピを検索することをお勧めします。誰かがラッパーTextをEntry持っていて、これらのソリューション (または他のソリューション) を機能させるために必要なすべての余分なものを隠しているので、適切なcountメソッドを作成するだけでよいのです。スタイルの検証を追加するラッパーさえあるかもしれません。TextEntry
これを行う方法は他にもいくつかありますが、いずれも欠点があります。
a を追加して、ウィジェットにアタッチされtraceた へのすべての書き込みをフックします。StringVarこれは、変数への書き込みによって発生します。初めて検証に使用しようとすると、無限再帰ループの問題が発生することを保証します。その後、将来、他のより微妙な問題に遭遇することになります。通常の解決策は、番兵フラグを作成することです。このフラグは、ハンドラーに入るたびにチェックして、再帰的に実行していないことを確認し、再帰イベントをトリガーできる何かを実行しているときに設定します。(edit_modified上記の例では、フラグを に設定した人を無視することができたので、これは必要ありませんでした。フラグを に設定したFalseだけFalseなので、無限再帰の危険はありません。)
<Key>仮想イベントから新しい文字 (または複数文字の文字列) を取得できます。しかし、その後、あなたはそれで何をしますか?どこに追加されるのか、どの文字が上書きされるのかなどを知る必要があります。シミュレートするすべての作業を行わない場合、Entryまたはさらに悪いことに、Text自分で編集する場合、これは単にやってlen(entry.get()) + 1ます。