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

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

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

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

Tkinter

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

Q&A

解決済

1回答

1877閲覧

Python3 Tkinter コンボボックスのエントリを押したかボタンを押したか判別したい

person

総合スコア224

Python 3.x

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

Tkinter

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

0グッド

0クリップ

投稿2021/07/02 10:37

編集2021/07/02 11:39

Tkinterでコンボボックスのエントリを押したかボタンを押したかを判別したいです。

コンボボックスの仮想バインドには、<<ComboboxSelected>> くらいしかなく、おそらく自分で処理を作る必要があると思います。

以下のように作ってみました。
一応、期待動作はするのですが、この方法だとOSやテーマを変えると、cb_btn_widthを変える必要が出てきます。
その都度自力で求めるのも面倒です。

ほかにいい方法があったら教えてください。
ボタン幅さえ取得できれば、それをcb_btn_widthに入れれば出来そうな気はするのですが・・・。

Python

1from tkinter import ttk 2import tkinter as tk 3 4def pushed_combobox(e): 5 cb_width = e.widget.winfo_width() 6 cb_btn_width = 20 # この値は自力で導く 7 cb_entry_width = cb_width - cb_btn_width 8 9 if cb_entry_width > e.x: 10 print("Entry") 11 else: 12 print("Button") 13 14win = tk.Tk() 15 16# テーマを変えるとボタン幅も変わってしまうため、cb_btn_width を変える必要あり 17#ttk.Style().theme_use("clam") 18 19cb = ttk.Combobox(win) 20# width やフォントサイズが変わってもボタン幅は変わらないため、cb_btn_width を変える必要なし 21#cb.configure(width = 30) 22#cb.configure(font = ("", 30)) 23cb.grid() 24 25cb.bind("<Button-1>", pushed_combobox) 26 27win.mainloop()

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

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

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

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

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

guest

回答1

0

ベストアンサー

テーマの間で共通の規格がない為、難しそうです。

  • entry で判断する方法
  • 矢印ボタンで判断する方法

例えばテーマが "clam" であれば arrowsize でボタンの大きさは得られますが
arrowsize が設定されてない場合や、他のテーマの場合は、
また違った対応が求められます。

python

1style = ttk.Style() 2style.theme_set("clam") 3style.configure("TCombobox", arrowsize=100) 4 5 6cb_btn_width = style.configure("TCombobox").get("arrowsize", 20)

矢印ボタンの部分は、
スタイルのうち「element」と呼ばれる、テーマ内での共通要素が用いられます。
具体的に何が使われているかは、テーマ毎に構成要素が異なります。

コンボボックスは、ttk.Entry と tk.List で構成されているので、
検討するなら、Entry 部分へのアクセスですが、
Python側でウィジェットとして直接アクセスする方法はなさそうです。

combobox のソースコード (TCL) では、内部で以下のように判断してます

tcl

1 set State(entryPress) [expr { 2 [$w instate !readonly] 3 && [string match *textarea [$w identify element $x $y]] 4 }]

Python になおすと identify() メソッドで問い合わせ

python

1import tkinter as tk 2from tkinter import ttk 3 4def onMotion(e): 5 element = e.widget.identify(e.x, e.y) 6 if "textarea" in element: 7 print(f"on Entry {element}") 8 else: 9 print(f"on Button ? {element}") 10 11root = tk.Tk() 12combo = ttk.Combobox(root) 13combo.bind("<Motion>", onMotion) 14combo.pack() 15root.mainloop()

これで、Entry 部分の判断は出来ますが、
ボタン部分の判断はまだ追加の作業が必要で、
テーマ毎にボタンの要素がどうなっているか調べる必要があります。
(スタイルから問い合わせるなら layout() メソッド)

例えば、上のコードでは左端の枠 padding や focus 部分等、
他の要素もボタン判定になってしまいます。

  • 訂正: ボタン判定の候補 if "downarrow" in element:

調べたついでに、ボタンの幅デフォルト値 20 は、width 14 + 両端 margins 6

c

1// ttkElements.c 2 3 { "-arrowsize", TK_OPTION_PIXELS, 4 offsetof(ArrowElement,sizeObj), "14" }, 5 6static const Ttk_Padding ArrowMargins = { 3,3,3,3 };

投稿2021/07/02 23:44

編集2021/07/03 12:17
teamikl

総合スコア8760

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

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

person

2021/07/03 01:40

単純にコンボボックスのエントリ部分が押されたのか、そうでない部分がおされたのかを判別する際は、identify()で判別したほうが良さそうですね。 ありがとうございます。
teamikl

2021/07/03 02:12

Entry は上記でほぼ判別付きそうですが、 別プラットフォーム/別テーマでの確認はとってません。 ボタン部分はテーマによっては、 rightdownarrow だったり downarrow するみたいです。 textarea や downarrow のないスタイル定義も可能かもしれないので、 何処まで対応するかといった話になってきそうですが、 現実的には、プラットフォーム毎に、よく使う主要なテーマのみ確認すれば良いと思います。 確認方法 from tkinter import Tk from tkinter import ttk # from ttkthemes import ThemedTk as Tk from pprint import pprint style = ttk.Style(Tk()) for name in style.theme_names():   style.theme_use(name)   print(f"## {name}")   pprint(style.layout("TCombobox")) テーマ別の各レイアウト情報に (right?)downarrow と textarea が含まれていることを確認する。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問