質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Q&A

解決済

2回答

2052閲覧

tkinter ボタンを押してもボタンの背景が変化せず、マウスポインタを動かすことで変化する。リアルタイムに変化させたい

goki_gottan

総合スコア168

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

0グッド

0クリップ

投稿2019/04/21 17:47

tkinterを使用し、ボタン5を押したら、そのボタンの背景が変わるという風にしたいです。
ボタンの背景は変わるのですが、マウスポイントを1度ボタンの上にもっていき、
その後、ズラすと変わるという感じです。
マウスポインタに依存せず、押せばすぐ変わるという風にしたいです。

また、ボタンを押すと、違うボタンであるボタン3をdisableにし指定しているのですが、
ボタンを押せてしまいます。
押せないようにしたいのですが、どのようにしたらいいでしょうか。
※ボタン3とは、ボタン3を押すとフォルダディレクトリを開くボタンにしております。

def callback5(event): if event.widget["bg"] == '#ffaacc': event.widget["bg"] = "SystemButtonFace" event.widget["text"] = "参照なし" event.widget["state"] = "disable" Button3.config(state="disable") else: event.widget["state"] = "active" event.widget["bg"] = "#ffaacc" event.widget["text"] = "参照あり" Button3.config(state="active") Button5 = tkinter.Button(text=u'', width=10,height=2,font=('Helvetica', '11',"bold"),foreground='#000000', background='#ffaacc') Button5.bind("<Button-1>",callback5) Button5.place(x=, y=)

いちお、半透明にはなるのですが、普通にボタン3を押して、ダイアログが開かれてしまいます。
背景色をリアルタイムに変更するのと込みでお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

マウスポインタに依存せず、押せばすぐ変わるという風にしたいです。

当方では再現せず、押すとすぐに背景が変わりました。
(Windows 10, CPython 3.7.0, Tcl/Tk 8.6)
環境(OSの違いやTcl/Tkのバージョンとか)による差なのか質問者さんが提示しておられない他の部分のコードに影響を受けていたりするのか・・・そのあたりは自分には何とも言えません。

ボタン3をdisableにし指定しているのですが、ボタンを押せてしまいます。

本来はdisableではなくdisabledだと思います。それはともかく、tkinterのウィジェットはdisableにしてもbindしたイベントの発火は抑止されないようです。しかしButtonインスタンスを生成する際のcommand引数に指定したハンドラーは抑止されるみたいです。

オンラインヘルプでButton.invokeのドキュメントを見ると

python

1>>> import tkinter as tk 2>>> help(tk.Button.invoke) 3Help on function invoke in module tkinter: 4 5invoke(self) 6 Invoke the command associated with the button. 7 8 The return value is the return value from the command, 9 or an empty string if there is no command associated with 10 the button. This command is ignored if the button's state 11 is disabled.

となってました。しかしButton.bindのドキュメントを見ても非活性の場合にイベントが発火しないといった説明は見当たりません。

対処としては

(1) command引数を用いる
Button3 = tk.Button(..., command=callback3)
のようにしてボタンを生成しbindを使わないようにすればdisable状態でハンドラーが起動しなくなります。ただ、command引数に指定したハンドラーにはイベントが渡ってこないのでボタンごとに異なるハンドラーを指定する必要がありそうです。つまりcallback5でやっておられるように「引数にわたってきたイベントのwidget属性を見ればどのボタンが押されたかがわかる」というふうにはできないので。

(2) bindに指定したハンドラーの中でdisable属性をチェックする

python

1def callback3(event): 2 if event.widget['state'] == 'disabled': 3 return 4 ...

こういう判定を一々やりたくはないので、もうちょっと工夫するならデコレーターを定義するなんて方法もアリかも知れません。

stateをチェックしてdisabledでない場合のみ関数を実行するといったデコレーターを定義しておきハンドラーを定義する際にそのデコレーターを指定するわけです。いくつものハンドラー関数のそれぞれに一々stateチェックを入れずに済むのでまぁまぁ我慢できるのではないでしょうか?

python

1def only_enabled(f): 2 def handle(event): 3 if event.widget['state'] != 'disabled': 4 f(event) 5 return handle 6 7@only_enabled 8def callback3(event): 9 ... 10 11... 12Button3.bind('<Button-1>', callback3) 13...

訂正・追記:

ご質問やコメント欄の内容を拝見していて

ボタンを押すと押されたままの状態になるので、return "break"

を入れている

どうもこれがピンとこなかったのですが、環境の違いじゃないかと思います。

自分はWindows 10でPython3.7にて動かしてみてたのですがそういう動きにはなりません。そこでふと環境の違いかなと思いUbuntuでやってみたところマウスhoverによって背景色が変化するといった動作は確認できました。WindowsやLinuxやMacにはそれぞれ仕様の異なるGUIサブシステムが入っているのはご存じかも知れません。例えばLinuxだとさらに複数のウィンドウマネージャーが存在しGnomeとMotifではボタンなどの振る舞いや外観がかなり違います。

環境固有の振る舞いは同じ環境でないと再現できないと思います。それゆえご自分の環境(OSやウィンドウマネージャーなど)を追記しましょう。もしあなたがMacintoshをお使いなら自分は持ってないので再現のやりようがないです。

Windows10ではご質問にあるような

・return "break"しないとボタンが押されたままになる
・マウスhoverしないと設定した背景色が反映されない

といった現象は起きないのです。

なお、本サイトではコメント欄にコード(特にインデントが重要な意味を持つPythonのコード)を書くのは避けるべきです。元の質問に不足内容があった場合は質問本文を編集してください。

投稿2019/04/21 20:42

編集2019/04/22 14:58
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

goki_gottan

2019/04/21 22:10

おっしゃる通り、bindよりcommandの方がいいと書いてますね。 ありがとうございました。 一度に全ての設定ができるのは魅力的てますね。
goki_gottan

2019/04/21 22:28

ボタンを押すと押されたままの状態になるので、return "break" を入れているのですが、それが悪さしていることがわかりました。 当方、tkのバージョンを確認したところ、8.6でしたので、コードが悪さしておりました。 しかしながら、return"break"を外すと、今度はボタンを押したときに、押されたままの絵になるのは不快です。 なにか他の方法はないでしょうか。
KSwordOfHaste

2019/04/21 23:46

問題が再現する最小限の完全なソースを質問文に明記した方がよいと思います。return "break"をしているというのは元の質問を見ても想像できませんでしたし・・・ 問題点も最初の質問内容と変わってきますので新たに質問を挙げなおすことをお勧めします。
goki_gottan

2019/04/22 12:56

def callback3(event): if event.widget["state"] == "disabled": event.widget["bg"] = "SystemButtonFace" return"break" else: event.widget["bg"] = "#ffaacc" fld1 = tkinter.filedialog.askdirectory(initialdir = dir) EditBox2.delete(0,tkinter.END) EditBox2.insert(0,fld1) return"break" def callback3(event):は、これを入れるようにしたのですが、 ruturn"break"がないとボタンを押された状態になりますし、あると色の変化がおかしくなります。
guest

0

xdotoolコマンドで、ボタンが押されたならすぐにマウスポインタをボタンの外側に動かすようにするのは如何でしょうか。

投稿2021/02/15 04:59

jw-tsuji

総合スコア3

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問