Tkinterの使い方:メニュー(Menu)の使い方

tkinterにおけるメニューの使い方の解説ページアイキャッチ

このページにはプロモーションが含まれています

このページでは、Tkinter の「メニュー」ウィジェットの作成方法・使い方・設定方法等について説明していきたいと思います。

メニューとは

まずは、今回解説する「メニュー」がどのようなウィジェットであるのかについて簡単に説明していきます。

メニューバーを構成するウィジェット

メニューウィジェットは、GUI アプリのメニューバーを構成するウィジェットになります。

皆さんも、メニューバーの存在する GUI アプリを利用されたことがあるのではないかと思います。このメニューバーに表示される項目からファイルを開いたり、ファイルを保存したり、何かを表示したり、何かの設定を行ったりすることが可能ですね!

Tkinter で開発する GUI アプリにおいても、メニューウィジェットを利用することで、このメニューバーの表示を行うことができるようになります。

メニューバーの説明図

ちなみに、Windows と Mac の場合とでメニューバーの表示される位置が異なるので注意してください。Windows の場合は、上の図のように GUI アプリのメインウィンドウの中にメニューバーが表示されることになります。それに対し、Mac の場合は、PC の画面の最上部にメニューバーが表示されることになります。

Macのメニューバーの表示位置

このように、Windows と Mac とではメニューバーの作りが大きく異なり、メニューウィジェットで実現できることにも違いがあります。具体的には Mac ではメニューバーの見た目の設定が反映されなかったり、メニューウィンドウの分離等が実行不可だったりします。ただ、基本的なメニューバーは Mac でもメニューウィジェットによって表示可能ですので、Mac 利用者の方も是非以降の解説を読み進めていただければと思います。

スポンサーリンク

メニューウィジェットはグループ

少し話が逸れましたが、もう少しメニューウィジェットについての説明を続けたいと思います。

このメニューウィジェットを使いこなす上でポイントになるのが、このメニューウィジェットは「複数の要素を含むグループ」であることをしっかりと理解しておく点になると思います。

皆さんの利用経験のある GUI アプリのメニューバーでも、下の図の青枠が示すように、メニューバーは複数のアイテムから構成されていたはずです。メニューウィジェットは、各項目そのものではなく、それらの項目を管理するグループのことになります。

メニューウィジェットが複数のメニューアイテムを管理するグループであることを示す図

また、これらの項目をクリックすると、プルダウンメニューとして新たなメニューのグループが表示されることになります。このグループもメニューウィジェットの1つとなります。

メニューウィジェットが複数のメニューアイテムを管理するグループであることを示す図2

さらに、このグループの中には、何かしらのアクションを実行する項目が含まれます。この項目をクリックすれば、例えばファイルを開いたり、直前の操作が取り消しされたり、何かしらのアプリの設定が行われたりすることになります。以降では、クリックすることで何かしらのアクションが実行される項目を「メニューアイテム」と呼びます。

メニューアイテムの説明図

ですが、このようなメニューアイテムだけでなく、次の階層のグループを示すアイテムが含まれていることもあります。そして、この次の階層のグループもメニューウィジェットとなります。

メニューウィジェットが複数のメニューアイテムを管理するグループであることを示す図3

つまり、メニューウィジェットとは、「メニューアイテム、及び、他のメニューウィジェットを要素とするグループ」と考えることができます。そして、メニューウィジェットに他のメニューウィジェットを追加することで、多階層のメニューバーを実現することができることになります。

メニューウィジェットの構成を示す図

ここまで説明してきたように、メニューウィジェットとはメニューアイテムと他のメニューウィジェットを要素とするグループのことです。メニューアイテム自体のことではないので注意してください。

また、メニューウィジェットの1つはアプリのメインメニューとして設定することが可能です。このメインメニューとして設定されたメニューウィジェットに含まれる要素が、アプリのメニューバーとして表示されることになります。そして、そのメニューバーのアイテムがクリックされた際に他のメニューグループが表示されるようにすることで、一般的な GUI のメニューバーを Tkinter で開発するアプリでも実現することができるようになります。

メインメニューから他のメニューウィジェットが表示される様子

このメニューウィジェットは作成時には空のグループとなります。そこに、メニューアイテムや他のメニューウィジェットを追加していくことで、メニューバーを作成していくことになります。このあたりは、次の章で詳しく解説していきます。

空のメニューウィジェットにメニューアイテムや他のメニューウィジェットを追加していく様子

ここからは、グループであることが分かりやすいよう、メニューウィジェットのことを必要に応じて「メニューグループ」と呼ばせていただきます。

メニューウィジェットの使い方

続いては、メニューウィジェットの使い方について解説していきたいと思います。

まずは、このメニューウィジェットを利用した簡単なアプリのスクリプト例を示したいと思います。ちょっと長いですが、基本的には同じようなことを何回も実施しているだけで、やっていることはシンプルです。

メニューウィジェットの利用例
import tkinter
import tkinter.font

def file_open():
    print('file_open')

def file_save():
    print('file_save')

def change_font():
    # 色メニューグループで選択された色に設定
    label.config(foreground=color_v.get())

    # フォントメニューグループで設定されたフォントに設定
    if italic_v.get():
        slant = tkinter.font.ITALIC
    else:
        slant = tkinter.font.ROMAN
    
    if bold_v.get():
        weight = tkinter.font.BOLD
    else:
        weight = tkinter.font.NORMAL

    font = tkinter.font.Font(size=40, slant=slant, weight=weight)
    label.config(font=font)

# メインウィンドウを作成
app = tkinter.Tk()
app.geometry('400x300')

# 色用のウィジェット変数を作成
color_v = tkinter.StringVar(value='red')

# 斜体設定用のウィジェット変数を作成
italic_v = tkinter.BooleanVar(value=False)

# 太字設定用のウィジェット変数を作成
bold_v = tkinter.BooleanVar(value=False)

# ラベルを作成して配置
label = tkinter.Label(
    app,
    text='Hello World',
)
label.pack()

# デフォルト設定で文字のフォントを設定
change_font()


"""メニューグループの作成"""

# メインメニューグループを作成
menu = tkinter.Menu(
    app
)

# ファイルメニューグループを作成
file_menu = tkinter.Menu(
    menu,
    tearoff=False
)

# 編集メニューグループを作成
edit_menu = tkinter.Menu(
    menu,
    tearoff=False
)

# 色メニューグループを作成
color_menu = tkinter.Menu(
    edit_menu,
    tearoff=False
)
# フォントメニューグループを作成
font_menu = tkinter.Menu(
    edit_menu,
    tearoff=False
)

"""メインメニューグループのアプリへの登録"""

# アプリのメニューバーにメニューグループを設定
app.config(menu=menu)

"""メニューグループへの要素の追加"""

# メインメニューグループへの要素の追加
menu.add_cascade(label='ファイル', menu=file_menu)
menu.add_cascade(label='編集', menu=edit_menu)

# ファイルメニューグループへの要素の追加
file_menu.add_command(label='開く', command=file_open)
file_menu.add_command(label='保存', command=file_save)

# 編集メニューグループへの要素の追加
edit_menu.add_cascade(label='色', menu=color_menu)
edit_menu.add_separator()
edit_menu.add_cascade(label='フォント', menu=font_menu)

# 色メニューグループへの要素の追加
color_menu.add_radiobutton(label='赤', variable=color_v, value='red', command=change_font)
color_menu.add_radiobutton(label='緑', variable=color_v, value='green', command=change_font)
color_menu.add_radiobutton(label='青', variable=color_v, value='blue', command=change_font)

# フォントメニューグループへの要素の追加
font_menu.add_checkbutton(label='斜体', variable=italic_v, command=change_font)
font_menu.add_checkbutton(label='太字', variable=bold_v, command=change_font)


# メインループ
app.mainloop()

このスクリプトを実行すれば、次の図のようなアプリが起動します。

スクリプトを実行すると起動するアプリ

ここで注目していただきたいのがメニューバーです。メニューバーに ファイル編集 のメニューが存在することが確認できると思います。また、ファイル をクリックすれば、開く保存 メニューが、編集 をクリックすれば フォント メニューが表示されることも確認できると思います。フォント の間には区切り線が存在することも確認できると思います。さらに、 メニューにマウスカーソルを合わせれば、 のメニューが表示され、フォント メニューにマウスカーソルを合わせれば、斜体太字 メニューが表示されることも確認できると思います。

メニューが多階層になっていることを示す図

このように、アプリのメニューバーは多階層な構成になっています。そして、これは、前述のようにメニューグループの要素としてメニューアイテムと他のメニューグループを追加することで実現しています。具体的には、下の図のように複数のメニューグループを用意し、それらを他のメニューグループの要素に追加することで実現しています。

各メニューグループの関係を示す図

さらに、編集 メニュー内の メニューから色を選択すれば、アプリに表示されている Hello World の文字列の色が変化することも確認できると思います。 同様に、編集 メニュー内の フォント メニューから 斜体太字 をクリックすれば、アプリに表示されている Hello World の文字列の形状が変化することも確認できるはずです。

メニューで選択した子横目に応じて表示される文字列の色やフォントが変化する様子

メニューバーを実現する上では、単にメニューを多階層な構成にするだけでなく、上記のように、クリックされたメニューアイテムに応じて何らかの処理が実行されるようにする必要もあります。上記では、アプリ上に表示されている文字列の色やフォントの変更を行っていますが、他にもファイルを開いたり、何らかのデータを保存したり、新たなウィンドウを表示したりするような処理がクリックされたメニューアイテムに応じて実行されるようにアプリを開発する必要があります。

クリックされたメニューに応じてアプリの設定や動作が変化する様子

ということで、メニューバーを実現する上では、「メニューグループ(メニューウィジェット)の作成」や「メニューグループへのメニューアイテムや他のメニューグループの追加」、さらには「メニューアイテムクリック時の処理の実行」のあたりがポイントになると思います。

特に、このあたりに注目しながら、ここからメニューウィジェットの使い方についての詳細を解説していきます。

メニューウィジェット(メニューグループ)の作成

まず、メニューウィジェットを使うためにはメニューウィジェットの作成が必要となります。

Menu クラスのコンストラクタ

メニューウィジェットは、tkinter の Menu クラスのコンストラクタを実行することで作成することができます。

メニューウィジェットの作成
# app はメインウィンドウ等の親ウィジェット
menu = tkinter.Menu(
    app
)

ここまで説明してきた通り、メニューウィジェットとはメニューグループのことになります。作成した時点ではメニューグループは空となっていますので、このメニューグループにメニューアイテムや他のメニューグループを追加する処理が必要となります。

また、その “他のメニューグループ” もメニューウィジェットとなりますので、メニューウィジェットは1つだけでなく、必要な分だけメニューウィジェットを作成する必要があることになります。前述で紹介したスクリプトにおいては、メニューウィジェットは下記の5つを作成しています。

  • menu
  • file_menu
  • edit_menu
  • color_menu
  • font_menu

Menu クラスのコンストラクタの引数

Menu クラスのコンストラクタの第1引数には、そのメニューグループが所属するウィジェットを指定します。例えば edit_menu に color_menu を追加するのであれば、color_menuedit_menu に所属することになるため、color_menu は下記のように作成する必要があります。

color_menuの作成
color_menu = tkinter.Menu(
    edit_menu
)

また、前述のスクリプトにおいては、Menu クラスのコンストラクタに引数 tearoff=False を指定するようにしています。この tearoff は、「分離実行アイテム」をメニューグループに追加するかどうかを指定する引数となります。

詳細は後述の tearoff の節で説明しますが、 メニューグループの「分離実行アイテム」をクリックすることで、そのメニューグループをアプリのウィンドウとは別のウィンドウに分離して表示することができます。

分離実行アイテムの説明図

この項目を表示するかどうかを指定するのが tearoff で、デフォルトは True となっています。ただ、こういったメニューグループの分離は通常のアプリでは不要な機能なので、tearoff=False を指定して分離実行アイテムを非表示にしています。

ちなみに、Mac の場合は tearoff の指定に関わらず分離実行アイテムは非表示になり、メニューグループの分離は不可となります。

スポンサーリンク

メインメニューの登録

メニューグループが必要な分だけ作成できれば、次はメインメニューグループの設定を行います。メインメニューグループとは、下の図の青枠部分のような、アプリに直接表示されるメニューバーに該当するメニューグループとなります。

メインメニューの説明図

このメインメニューグループの設定は、下記のように引数に menu=メインメニューグループ を指定して config メソッドをアプリに実行させることで実施できます。

メインメニューグループの設定
アプリ.config(menu=メインメニューグループ)

例えば、アプリが appmenu をメインメニューグループに設定したいのであれば、下記を実行すれば良いことになります。

メインメニューグループの設定例
app.config(menu=menu)

これにより、menu がメインメニューグループに設定され、アプリのメニューバーとして表示されるようになります。

configメソッドでメインメニューグループを設定する様子

後は、そのメインメニューグループにメニューアイテムや他のメニューグループ等の要素を追加して、あなたが望むメニューバーを実現していけばよいだけになります。

メニューグループへの要素の追加

ということで、次はメニューグループへの要素の追加について解説していきます。ここまで、メニューグループへ追加可能な要素としては、メニューグループ・メニューアイテムの2種類を用いて説明してきましたが、より詳細にはメニューグループには下記の5つの要素を追加することが可能です。

  • メニューグループ
  • コマンドメニューアイテム
  • チェックボタンメニューアイテム
  • ラジオボタンメニューアイテム
  • セパレーター

そして、この要素の追加はメニューグループにメソッドを実行させることで実施することができます。このメソッドは追加する要素の種類ごとに用意されており、各要素を追加するメソッドは下記のようになります。以降の解説では、これらを総称して呼ぶ場合には add_xxxxx メソッドと呼ばせていただきます。

  • add_cascade:メニューグループの追加
  • add_command:コマンドメニューアイテムの追加
  • add_checkbutton:チェックボタンメニューアイテムの追加
  • add_radiobutton:ラジオボタンメニューアイテムの追加
  • add_separator:セパレーターの追加

ここからは、これら5つの要素の追加の仕方や各種メソッドの使い方について解説していきます。

メニューグループの追加

メニューグループへの他のメニューグループの追加は add_cascade メソッドで実施することができます。

add_cascadeメソッドの説明図

add_cascade メソッド

add_cascade メソッドは、引数 labelアイテム名 を指定し、さらに引数 menu追加したいメニューグループ を指定して実行します。

add_cascadeの実行
メニューグループ.add_cascade(
    label='アイテム名',
    menu=追加したいメニューグループ
)

これにより、メソッドを実行したメニューグループに対して、引数で指定した アイテム名 のアイテムが追加され、さらに、そのアイテムをクリックしたりマウスカーソルを合わせたりしたときに、引数で指定した 追加したいメニューグループ が表示されるようになります。

add_cascadeメソッドの説明図2

add_cascade メソッドの実行例

前述で示したスクリプトにおいては、下記のようにメインメニューグループとなる menu に2回 add_cascade メソッドを実行させています。

menuからのadd_cascadeの実行
menu.add_cascade(label='ファイル', menu=file_menu)
menu.add_cascade(label='編集', menu=edit_menu)

そのため、メニューバーには ファイル編集 が表示されるようになり、さらに、ファイル にマウスカーソルを合わせれば file_menu が、編集 にマウスカーソルを合わせれば edit_menu が表示されることになります。

add_cascadeメソッドとメニューグループの関係性を示す図1

また、edit_menu に対しても下記のように 2回 add_cascade メソッドを実行させています(add_separator については後述で解説します)。

edit_menuからのadd_cascadeの実行
edit_menu.add_cascade(label='色', menu=color_menu)
edit_menu.add_separator()
edit_menu.add_cascade(label='フォント', menu=font_menu)

そのため、編集 のクリックによって表示されるメニューには フォント が追加され、さらに にマウスカーソルを合わせれば color_menu が、フォント にマウスカーソルを合わせれば font_menu が表示されることになります。

add_cascadeメソッドとメニューグループの関係性を示す図2

このように、メインメニューグループに add_cascade メソッドでメニューグループを追加し、さらにそれらのメニューグループに add_cascade メソッドで他のメニューグループを追加していくことで、多階層のメニューバーが実現できることになります。

スポンサーリンク

コマンドメニューアイテムの追加

メニューグループへのコマンドメニューアイテムの追加は add_command メソッドで実施することができます。

add_commandメソッドの説明図

コマンドメニューアイテムとは、クリック時に何らかの処理が実行されるメニューアイテムとなります。

コマンドメニューアイテムの説明図

add_command

add_command は、引数 labelアイテム名 を指定し、さらに引数 commandクリック時に実行する関数(or メソッド)を指定して実行します。

add_commandの実行
メニューグループ.add_command(
    label='アイテム名',
    command=クリック時に実行する関数
)

command 引数で クリック時に実行する関数 を指定するという点は、下記ページで解説しているボタンウィジェットと同様になります。なので、見た目はボタンとは異なりますが、イメージとしては add_command はボタンウィジェットをメニューグループに追加するメソッドとなります。

ボタンウィジェット作成解説ページのアイキャッチ Tkinterの使い方:ボタンウィジェット(Button)の使い方

add_command の実行例

前述で示したスクリプトにおいては、下記のように file_menu に2回 add_command メソッドを実行させています。

file_menuからのadd_commandの実行
file_menu.add_command(label='開く', command=file_open)
file_menu.add_command(label='保存', command=file_save)

そのため、file_menu のグループには 開く と 保存 のアイテムが追加され、さらに、開く をクリックすれば file_open が、保存 をクリックすれば file_save が実行されることになります。

コマンドメニューアイテムをクリックすることでcommand引数に指定された関数が実行される様子

前述のスクリプトでは、これらの関数は単に print を実行しているだけになりますが、例えば下記のページで紹介しているファイル選択ダイアログを表示するようにすれば、これらがクリックされた時にファイルを選択することができるようになり、選択されたファイルを開いたり、選択されたファイルに何らかの情報を保存したりするようなことも可能になります。

ファイル選択画面表示の解説ページアイキャッチ Python でファイル選択画面を表示する

もちろん、command に指定する関数の作り方によって、他にもさまざまな処理を実行するメニューアイテムが実現可能となります。

チェックボタンメニューアイテムの追加

メニューグループへのチェックボタンメニューアイテムの追加は add_checkbutton メソッドで実施することができます。

add_checkbuttonメソッドの説明図

チェックボタンメニューアイテムとは、何らかの設定の ON / OFF を切り替えるメニューアイテムとなります。”チェックボタン” が名前に付いていることからも分かるように、このチェックボタンメニューアイテムは下記ページで解説しているチェックボタンウィジェットのメニューアイテムバージョンとなります。

チェックボタンの解説ページアイキャッチ Tkinterの使い方:チェックボタン(Checkbutton)の使い方

使い方もチェックボタンウィジェットと同様で、チェックボタンメニューアイテムはクリックするたびに、そのメニューの左側に表示されるチェックマークの ON / OFF が切り替わるようになっています。そして、そのメニューアイテムの ON / OFF に応じてアプリの動作を変化させることで、ユーザーがアプリの設定や機能等をメニューから ON / OFF できるようになります。

チェックボタンメニューアイテムの説明図

add_checkbutton

add_checkbutton は、引数 labelアイテム名 を指定して実行する必要があります。また、チェックボタンの ON / OFF の状態を判別するためには、引数 variable に ON/OFF判別用のウィジェット変数 を指定する必要があります。さらに、チェックボタンメニューアイテムがクリックされた時に何らかの関数が実行されるようにしたいのであれば、引数 commandクリック時に実行する関数 を指定する必要があります。

add_checkbuttonの実行
メニューグループ.add_checkbutton(
    label='アイテム名',
    variable=ON/OFF判別用のウィジェット変数,
    command=クリック時に実行する関数
)

この「引数 variable にウィジェット変数を指定して後からチェックの ON / OFF を判別できるようにする」という点に関しても先ほど紹介したチェックボックスと同様になります。チェックが ON / OFF の時にウィジェット変数にセットされる値を True / False から変更したいのであれば、add_checkbutton に引数 onvalueoffvalue を指定してやれば良いです。このあたりもチェックボックスと同様になります。

チェックボタンメニューアイテムとウィジェット変数との関係

また、ここで使用しているウィジェット変数に関しては下記ページで解説していますので、詳細を知りたい方は下記ページを参照してください。

ウィジェット変数の解説ページのアイキャッチ Tkinterの使い方:ウィジェット変数について解説【StringVar・BooleanVar・IntVar・DoubleVar】

add_checkbutton の実行例

前述で示したスクリプトにおいては、下記のように font_menu に2回 add_checkbutton メソッドを実行させています。

font_menuからのadd_checkbuttonの実行
font_menu.add_checkbutton(label='斜体', variable=italic_v, command=change_font)
font_menu.add_checkbutton(label='太字', variable=bold_v, command=change_font)

そのため、font_menu のグループには 斜体 と 太字 のアイテムが追加され、斜体 をクリックすれば italic_v にセットされる値が True / False で切り替わることになります。また、その値に応じて、斜体 のアイテムの左に表示されるチェックマークが表示されたり消えたりすることになります。同様に、太字 をクリックすれば bold_v にセットされる値が True / False で切り替わることになりますし、その値に応じて、太字 のアイテムの左に表示されるチェックマークが表示されたり消えたりすることになります。

さらに、これらの 斜体 や 太字 のアイテムがクリックされた際には change_font が実行されるようになっており、この change_font の中で italic_v にセットされている値とbold_v にセットされている値を取得し、Hello World を表示しているラベルウィジェットに対して、それぞれの値に応じたフォントを設定するようにしています。そのため、これらがクリックされたタイミングで、Hello World の文字列のフォントが変化することになります。

クリック時にチェックのON/OFFに応じてアプリの設定が変化する様子

このように、add_checkbutton や次に説明する add_radiobutton で追加したメニューアイテムに関しては、単にメニューグループに追加するだけでなく、それらのメニューアイテムにセットされている値を後から取得し、それをアプリの動作や見た目・設定に反映するような処理も必要となります。そのため、それが実現できるようにメニューアイテムの追加時に実行するメソッドに適切な引数を指定する必要があり、このあたりがメニューウィジェットを使いこなす上での1つのポイントになると思います。

また、このページで紹介している例においては add_checkbuttoncommand 引数を指定していますが、これはメニューアイテムクリック時に処理を実行したいからであって、別に command 引数が必須というわけではないので注意してください。例えばボタンウィジェットを別途用意し、それがクリックされた時にチェックメニューアイテムのチェックの ON / OFF を取得し、それをアプリの設定や動作に反映するのでも良いです。

メニューアイテムクリック時ではなく、ボタンクリック時にチェックのON/OFFを取得する様子

ラジオボタンメニューアイテムの追加

メニューグループへのラジオボタンメニューアイテムの追加は add_radiobutton メソッドで実施することができます。

add_radiobuttonメソッドの説明図

ラジオボタンメニューアイテムとは、複数のラジオボタンメニューアイテムの中から1つのみを選択可能とするためのメニューアイテムとなります。”ラジオボタン” が名前に付いていることからも分かるように、このラジオボタンメニューアイテムは下記ページで解説しているラジオボタンウィジェットのメニューアイテムバージョンとなります。

tkinterのラジオボタンの使い方の解説ページアイキャッチ Tkinterの使い方:ラジオボタン(Radiobutton)の使い方

使い方もラジオボタンウィジェットと同様で、ラジオボタンメニューアイテムは複数のラジオボタンメニューアイテムでグループ化され、そのうちの1つが選択されると他のものが選択解除されるようになっています。そして、その選択されているメニューアイテムに応じてアプリの動作を変化させることで、ユーザーがアプリの設定や機能等をメニューから選択できるようになります。

ラジオボタンメニューアイテムの説明図

add_radiobutton の実行例

add_radiobutton は、引数 labelアイテム名 を指定して実行する必要があります。また、複数のラジオボタンメニューアイテムをグループ化する&選択中のラジオボタンメニューを判別するために引数 variable選択中のアイテム判別用のウィジェット変数 を指定する必要があります。さらに、引数 value には、そのラジオボタンメニューアイテムが選択されているときに ウィジェット変数に設定する値 を指定します。ラジオボタンメニューアイテムがクリックされた時に何らかの関数が実行されるようにしたいのであれば、引数 commandクリック時に実行する関数 を指定する必要があります。

add_radiobuttonの実行
メニューグループ.add_radiobutton(
    label='アイテム名',
    variable=選択中のアイテム判別用のウィジェット変数,
    value=ウィジェット変数に設定する値,
    command=クリック時に実行する関数
)

前述の通り、ラジオボタンメニューアイテムは、同一のグループ内のアイテムのうち1つのみが選択可能となります。複数のアイテムのうち、1つのみを選択可能としたいのであれば、それらのアイテムに対応するラジオボタンメニューアイテムは同じグループとする必要があります。そして、ラジオボタンメニューアイテムは、variable が同じウィジェット変数であるものが同じグループとして扱われるようになるため、グループ化したいラジオボタンメニューアイテムの variable には、同じウィジェット変数を指定する必要があります。

ラジオボタンメニューアイテムとウィジェット変数の関係を示す図1

また、そのウィジェット変数には、選択中のラジオボタンメニューアイテムの value に指定された値がセットされることになります。したがって、そのウィジェット変数にセットされている値を取得すれば、どのラジオボタンメニューアイテムが選択中であるかを判別することができるようになります。ただし、同じグループのラジオボタンメニューアイテムの value が重複すると判別できなくなるため、同じグループのラジオボタンメニューアイテムには異なる value を指定する必要があります。

ラジオボタンメニューアイテムとウィジェット変数の関係を示す図2

add_radiobutton の実行例

前述で示したスクリプトにおいては、下記のように color_menu に3回 add_radiobutton メソッドを実行させています。

font_menuからのadd_radiobuttonの実行
color_menu.add_radiobutton(label='赤', variable=color_v, value='red', command=change_font)
color_menu.add_radiobutton(label='緑', variable=color_v, value='green', command=change_font)
color_menu.add_radiobutton(label='青', variable=color_v, value='blue', command=change_font)

そのため、color_menu のグループには のアイテムが追加され、これらは同じグループのラジオボタンメニューアイテムとして扱われることになります。そして、 をクリックして選択すれば color_v にセットされる値が 'red' に、 をクリックして選択すれば color_v にセットされる値が 'green' に、 をクリックして選択すれば color_v にセットされる値が 'blue' に変化するようになっていますし、選択されたアイテムに応じて左側に表示されるチェックマークの位置が変化するようになっています。

さらに、これらの のアイテムがクリックされた際にも change_font が実行されるようになっており、この change_font の中で color_v にセットされている値を取得し、Hello World を表示しているラベルウィジェットに対して、取得した値に応じた文字色を設定するようにしています。そのため、これらがクリックされたタイミングで、Hello World の文字列の色が変化することになります。

クリック時に選択されたアイテムに応じてアプリの設定が変化する様子

基本的には、チェックボタンメニューアイテムと使い方は似ていますので、チェックボタンとラジオボタンの性質の違いはありますが、そこを理解すれば、両方とも上手く使いこなすことができるようになると思います。

スポンサーリンク

セパレーターの追加

メニューグループへのセパレーターの追加は add_separator メソッドで実施することができます。

add_separatorの説明図

セパレーターとは、アイテムとアイテムの間に挿入する区切り線のことになります。

セパレーターの説明図

add_separator

add_separator メソッドの使い方は非常に単純で、このメソッドを追加したいメニューグループに引数なしで実行させればよいだけです。

add_separatorの実行
メニューグループ.add_separator()

add_separator の実行例

前述で示したスクリプトにおいては、下記のように edit_menu に1回 add_separator メソッドを実行させています。

font_menuからのadd_radiobuttonの実行
edit_menu.add_cascade(label='色', menu=color_menu)
edit_menu.add_separator()
edit_menu.add_cascade(label='フォント', menu=font_menu)

上記のように add_separator を実行させることで、 のアイテムと フォント のアイテムの間に区切り線が追加されることになります。

特に、これらの間に区切り線を追加した意味もないのですが、add_separator の利用例を示すために add_separator を実行させるようにしています。実際のアプリの開発時には、何か意味合いの大きく変わるアイテムの間に add_separator で区切り線を追加してやるのが良いと思います。

以上が、メニューウィジェット(メニューグループ)の基本的な使い方となります。

基本的には、ここまで説明してきた内容を理解していただければ、メニューバーを自身で作成することができるようになるのではないかと思います。

ただし、ここまでの解説の中で説明していない Menu のコンストラクタや add_xxxxx メソッドに指定可能な引数や、メニューグループに実行させることのできるメソッドもありますので、ここからは、それらについて解説していきたいと思います。

正直言うと、メニューバーに関してはそんなに見た目にこだわる必要もないと思いますので、前述の通り、ここまで説明した内容を理解しておけば、実現したいメニューバーは自身で実現できると思います。なので、ここからは興味のある方のみ読み進めていただければ良いと思います。

メニューウィジェットの設定

では、ここからは、メニューウィジェットの設定について解説していきます。

他のウィジェット同様に、メニューウィジェットの見た目等の設定はコンストラクタ(tkinter.Menu())にキーワード引数を指定することで変更可能です。コンストラクタに指定可能なキーワード引数名は下記により確認することができます。

設定可能なキーワード
# menu:メニューウィジェット
print(menu.keys())

ここでは、私が動作を理解している設定に対する解説のみを行わせていただきます。具体的には、下記の設定について説明していきます。

MEMO

私の下記環境での実行結果をもとに説明していますが、環境によっては動きが異なるかもしれません

実際にご自身の環境で実行結果を確認していただくと、より確実に設定の効果を理解することができると思います

  • OS:Windows 11
  • Python:3.12
  • Tkinter:8.6

メニューウィジェットの設定の注意点

メニューウィジェットの設定に関しては、いくつか注意点があるため、その点についてまず説明しておきます。

あくまでもメニューグループに対する設定である

Menu クラスのコンストラクタのキーワード引数の指定によって変更可能なのは、あくまでもメニューグループに対する設定になります。個別のメニューアイテムに対する設定の変更に関しては、そのメニューアイテムを追加するときに実行する add_xxxxx メソッドへのキーワード引数の指定によって実施する必要があります。add_xxxxx メソッドに指定可能な引数に関しては、後述の add_xxxxx メソッドの引数 で説明していきます。

Menuのコンストラクタの引数とadd_xxxxxの引数の意味合いの違いを示す図

メインメニューグループには適用されない?

少なくとも私が試した感じでは、メインメニューグループの見た目等の設定の変更は不可でした。また、後述でも解説する「分離実行アイテム」も表示されないようになっています。

なので、もしかしたら環境依存かもしれませんが、メインメニューグループの設定は基本的に変更不可である可能性が高いです。以降の解説では、私の環境で動作確認済みの内容を説明していくのですが、これらはメインメニューグループ以外のメニューグループで動作確認を行っていますので、その点はご注意ください。

Mac では多くの設定が反映されない?

また、これはおそらくメニューグループだけでなく、メニューアイテムに対しても言えることだと思うのですが、以降で解説する設定は Mac の場合には無効であるものが多いです。少なくとも色の変更は不可でしたし、ウィンドウの分離等も不可のようでした。フォントサイズの変更は可能でした。

今後紹介する引数による設定は、Mac の場合は無効である可能性が高いので注意してください。

スポンサーリンク

background

では、ここからメニューウィジェットの設定を変更するキーワード引数の紹介を行っていきます。

まず、background は、通常時のメニューグループの背景色を設定するキーワード引数となります。background に関しては、略して bg キーワード引数で指定することも可能です。 

background引数の説明図

background の値としては、色名やカラーコード等を指定することが可能です。

例えば下記のようにメニューグループを生成すれば、そのメニューグループの背景色が赤色に変化することになります。

backgroundの指定例
menu = tkinter.Menu(
    # 略
    background='red'
)

foreground

foreground は、通常時のメニューグループの文字色を設定するキーワード引数となります。foreground に関しては、略して fg キーワード引数で指定することも可能です。 

foreground引数の説明図

foreground の値としては、色名やカラーコード等を指定することが可能です。

例えば下記のようにメニューグループを生成すれば、そのメニューグループのメニューアイテムの文字色が緑色に変化することになります。

foregroundの指定例
menu = tkinter.Menu(
    # 略
    foreground='green'
)

activebackground

activebackground は、カーソルを合わせたメニューアイテムの背景色を設定するキーワード引数となります。

activebackground引数の説明図

activebackground の値としては、色名やカラーコード等を指定することが可能です。

例えば下記のようにメニューグループを生成すれば、そのメニューグループの背景色は通常時は赤色になりますが、カーソルを合わせた箇所のみ背景色が青色に変化することになります。

activebackgroundの指定例
menu = tkinter.Menu(
    # 略
    background='red',
    activebackground='blue'
)

スポンサーリンク

activeforeground

activeforeground は、カーソルを合わせたメニューアイテムの文字色を設定するキーワード引数となります。

activeforeground引数の説明図

activeforeground の値としては、色名やカラーコード等を指定することが可能です。

例えば下記のようにメニューグループを生成すれば、そのメニューグループの文字色は通常時は緑色になりますが、カーソルを合わせた箇所のみ文字色が白色に変化することになります。

activeforegroundの指定例
menu = tkinter.Menu(
    # 略
    foreground='green',
    activeforeground='white'
)

selectcolor

selectcolor は、チェックマークの色を設定するキーワード引数となります。チェックボタンメニューアイテムやラジオボタンメニューアイテムに関しては、ON のアイテムや選択されたアイテムの左側にはチェックマークが表示されることになります。selectcolor を指定することで、このチェックマークの色を変更することができます。

selectcolor引数の説明図

selectcolor の値としては、色名やカラーコード等を指定することが可能です。

例えば下記のようにメニューグループを生成すれば、そのメニューグループ内に表示されるチェックマークの色がピンク色に変化することになります。

selectcolorの指定例
menu = tkinter.Menu(
    # 略
    selectcolor='pink'
)

disabledforeground

disabledforeground は、無効化されたメニューアイテムの文字色を設定するキーワード引数となります。後述の state で説明する通り、メニューアイテムは state 引数によって無効化(クリック不可)することが可能です。disabledforeground を指定することで、この無効化されたアイテムの文字色を変更することができます。

disabledforeground引数の説明図

disabledforeground の値としては、色名やカラーコード等を指定することが可能です。

例えば下記のようにメニューグループを生成すれば、そのメニューグループ内に表示される無効化されたアイテムの文字色が黄色に変化することになります。

disabledforegroundの指定例
menu = tkinter.Menu(
    # 略
    disabledforeground='yellow'
)

スポンサーリンク

font

font は、メニューグループ内のメニューアイテムのアイテム名のフォントを設定するキーワード引数となります。

font引数の説明図

font の値としては、tkinter.font.Font のオブジェクトや、タプル等を指定することが可能です。フォントの指定の仕方に関しては下記ページでまとめていますので、必要に応じて下記ページを参照してください。

フォント指定解説ページのアイキャッチ Tkinterの使い方:フォントの指定方法

例えば下記のようにメニューグループを生成すれば、そのメニューグループ内に表示されるアイテムの文字のフォントサイズが 40 に変化することになります。

fontの指定例
menu = tkinter.Menu(
    # 略
    font=('', 40)
)

postcommand

postcommand は、そのメニューグループが表示された時に実行する処理を設定するキーワード引数となります。基本的には、メニューグループ表示時には単にそのグループが表示されるだけになりますが、postcommand を指定することで、表示時に同時に何かしらの処理を実行することができるようになります。

postcommand引数の説明図

postcommand には、関数やメソッド等を指定することが可能です。ただし、関数に関しては引数なし、メソッドに関しては引数が self のみである必要があります。

例えば下記のようにメニューグループを生成すれば、そのメニューグループが表示されるタイミングで Hello World が出力されるようになります。

postcommandの指定例
def print_hello():
    print('Hello World')

menu = tkinter.Menu(
    # 略
    postcommand=print_hello
)

tearoff

tearfoff は、そのメニューグループをメインウィンドウから分離可能とするかどうかを設定するキーワード引数となります。

tearoff引数の説明図

分離可能と設定されている場合、そのメニューグループの先頭には分離実行アイテムが表示されることになります。そして、それをクリックすることで、メニューグループのメインウィンドウからの分離を行うことができます。

分離実行アイテムの説明図

tearfoff には BOOL 値(True / False)を指定します。また、tearfoff のデフォルト値は True となります。ですが、メインメニューグループの場合は tearfoff の指定に関わらず分離不可となります。

例えば下記のようにメニューグループを生成すれば、そのメニューグループはメインウィンドウからの分離は不可となります。

tearoffの指定例
menu = tkinter.Menu(
    # 略
    tearoff=False
)

スポンサーリンク

tearoffcommand

teaoffcommand は、そのメニューグループが分離された時、すなわち分離実行アイテムがクリックされたときに実行する処理を設定するキーワード引数となります。分離するためには tearfoff=True が指定されている or tearfoff 引数が指定されていない必要があるため、tearfoff=False が指定されている場合は、この引数は意味を持ちません。

tearoffコマンドの説明図

tearoffcommand には、関数やメソッド等を指定することが可能です。ただし、関数に関しては引数2つ、メソッドに関しては引数が self +2つである必要があります。

例えば下記のようにメニューグループを生成すれば、そのメニューグループが分離されるタイミングで Hello World が出力されるようになります。

postcommandの指定例
def print_hello(a, b):
    print('Hello World')

menu = tkinter.Menu(
    # 略
    tearoffcommand=print_hello
)

borderwidth

borderwidth は、特に分離されたメニューグループの外枠の太さを設定するキーワード引数となります。

borderwidth引数の説明図

補足しておくと、おそらく分離前のメニューグループにも boarderwidth を指定する効果はあります。ですが、私が試した感じだと、チェックマークの位置が変な位置に移動するだけで外枠の太さが変化することはありませんでした。つまり、boarderwidth によって分離されたメニューグループの太さは適切に設定可能ですが、分離されていないメニューグループの表示が変になる可能性があります。なので、この引数は指定しない方が良いかなぁと思います。環境にもよるかもしれませんが…。

一応説明を続けると、borderwidth には整数を指定します。単位はピクセルになると思います。

例えば下記のようにメニューグループを生成すれば、分離されたメニューグループの外枠の幅が 10 ピクセルに変化します。

borderwidthの指定例
menu = tkinter.Menu(
    # 略
    borderwidth=10
)

relief

relief は、分離されたメニューグループの見た目を設定するキーワード引数となります。

relief引数の説明図

relief に指定可能な値や、それらの値を指定したときのウィジェットの見た目に関しては下記ページで解説していますので、詳しくは下記ページの relief をご参照ください(フレームの例で説明していますが、見た目の変化に関してはメニューグループにおいても同様になります)。

フレームウィジェットの作り方の解説ページアイキャッチ Tkinterの使い方:フレームウィジェット(Frame)の使い方

relief の指定によってウィジェットの見た目が変化するのは外枠が太い場合です。ですが、前述の通り boarderwidth を指定すると分離前のメニューグループに悪影響がありそうなので、この relief の指定もオススメしません。見た目を変化させたい場合は、まずは relief の指定と boarderwidth の指定による分離前・分離後のメニューグループの見た目を確認してみてください。

例えば下記のようにメニューグループを生成すれば、分離されたメニューグループが浮き出したような見た目に変化します。

reliefの指定例
menu = tkinter.Menu(
    # 略
    borderwidth=10,
    relief=tkinter.RAISED
)

スポンサーリンク

cursor

cursor は、分離されたメニューグループにマウスカーソルを合わせたときのカーソルの見た目を設定する引数となります。

cursor引数の説明図

cursor に指定可能な値に関しては、公式の下記ページで紹介されていますので、下記ページを参考にしていただければと思います。

https://tcl.tk/man/tcl8.6/TkCmd/cursors.htm

例えば下記のようにメニューグループを生成すれば、分離されたメニューグループにマウスカーソルを合わせたときのカーソルの見た目が「手」に変化します(Windows の場合は)。

cursorの指定例
menu = tkinter.Menu(
    # 略
    cursor='hand1'
)

title

title は、分離されたメニューグループのウィンドウのタイトルを設定する引数となります。

title引数の説明図

title には文字列を指定します。title を指定しなかった場合は、分離されたメニューグループのウィンドウのタイトルには label に指定した文字列が設定されるようになっています。

例えば下記のようにメニューグループを生成すれば、分離されたメニューグループのウィンドウのタイトルが menu に変化します(Windows の場合は)。

titleの指定例
menu = tkinter.Menu(
    # 略
    title='menu'
)

add_xxxxx メソッドの引数

続いて、下記のメソッドに指定可能なキーワード引数について解説していきます。ちなみに、add_separator に関しては指定可能な引数は無いです。 

  • add_cacscade
  • add_command
  • add_checkbutton
  • add_radiobutton

具体的には、下記のキーワード引数の紹介を行っていきます。

ここまでに説明してきたのはメニューウィジェット、すなわちメニューグループに対する設定となります。それに対し、ここから説明するのは、上記のメソッドへのキーワード引数の指定による「メニューグループの中の個別のメニューアイテムに対する設定」となります。

Menuのコンストラクタの引数とadd_xxxxxの引数の意味合いの違いを示す図

また、メニューウィジェット生成時に指定可能なキーワード引数と、上記のメソッドに指定可能なキーワード引数とは一部重複します。重複してキーワード引数が指定された場合は、上記のメソッド側に対するキーワード引数、すなわちメニューアイテムに対する設定が優先されることになります。例えば、メニューグループの背景色のみを緑色に設定した場合は、そのメニューグループの背景色は当然緑色になりますが、そのメニューグループに追加するメニューアイテムに対して背景色を白色に設定した場合、メニューアイテムに対する設定、つまり add_xxxxx  の引数による設定が優先されて、そのメニューアイテムの背景色は白色となります。

add_xxxxxによる設定が優先されることを示す図

このあたりを理解した上でメニューウィジェットに対する設定およびメニューアイテムに対する設定を実施するようにしていただくと、意図したとおりの設定が行えるようになると思います。

また、ここから add_xxxxx メソッドに指定可能なキーワード引数の紹介を行っていきますが、各種キーワード引数が add_xxxxx のメソッドの全てに指定可能というわけではありません。そのため、次のような表を使って、各メソッドに指定可能なキーワード引数を示すようにしていきたいと思います。

雰囲気で理解していただけると思いますが、念のため説明しておくと、cascadeadd_cascadecommandadd_commandcheck は add_checkbuttonradio は add_radiobutton をそれぞれ表しており、〇が付いているメソッドは、そのキーワード引数が指定可能、×が付いているメソッドは、そのキーワード引数が指定不可であることを示しています。

cascade command check radio
× ×

スポンサーリンク

label

では、add_xxxxx メソッドに指定可能なキーワード引数を紹介していきます。

まず、label は、追加するメニューアイテムの表示名を設定するキーワード引数となります。

label引数の説明図

label は全メソッドに対して指定可能なキーワード引数となります。

cascade command check radio

label の値には文字列を指定します。

また、label の値を指定しなかった場合、add_cascade の場合は表示名が ()、それ以外の場合は空白となるようです。

例えば下記のように add_command を実行すれば、実行したメニューウィジェットに表示名が 開く であるコマンドメニューアイテムが追加されることになります。

labelの指定例
# menu:メニューウィジェット
menu.add_command(
    # 略
    label='開く'
)

menu は、追加するメニューグループを設定するキーワード引数となります。

menu引数の説明図

メニューグループを追加することのできるメソッドは add_cascade のみであるため、この menu が指定できるのは add_cascade のみとなります。

cascade command check radio
× × ×

menu の値にはメニューグループ、すなわちメニューウィジェットを指定します。

例えば下記のように add_cascade を実行すれば、実行したメニューウィジェットに file_menu というメニューグループが追加されることになります。

menuの指定例
# menu,file_menu:メニューウィジェット
menu.add_command(
    # 略
    menu=file_menu
)

command

command は、追加するメニューアイテムがクリックされた時に実行する処理を設定するキーワード引数となります。

command引数の説明図

command は全メソッドに対して指定可能なキーワード引数となります。特に add_command は、クリックされた時に何らかの処理を実行するメニューアイテムを追加するためのメソッドとなるため、add_command に関しては基本的に command の指定は必須であると考えて良いです。

cascade command check radio

command には、関数やメソッド等を指定することが可能です。ただし、関数に関しては引数なし、メソッドに関しては引数が self のみである必要があります。

例えば下記のように add_command を実行すれば、追加されたメニューアイテムがクリックされた時に Hello World が出力されるようになります。

commandの指定例
def print_hello():
    print('Hello World')

# menu:メニューウィジェット
menu.add_command(
    # 略
    command=print_hello
)

スポンサーリンク

variable

variable は、追加するメニューアイテムと連動するウィジェット変数を設定するキーワード引数となります。

variable引数の説明図

variableadd_checkbuttonadd_radiobutton に指定可能なキーワード引数となります。

cascade command check radio
× ×

variable にはウィジェット変数を指定することが可能です。メニューウィジェットの使い方 でも説明したように、チェックボタンメニューアイテムであれば、そのメニューアイテムのチェックが ON / OFF (チェックマーク有 / 無)のどちらの状態であるかをウィジェット変数から判別できるようになります。また、ラジオボタンメニューアイテムであれば、複数のラジオボタンメニューアイテムの内、どれが選択されているのかをウィジェット変数から判別できるようになります。

さらに、これも メニューウィジェットの使い方 で説明したように、ラジオボタンメニューアイテムの場合は、同じウィジェット変数が variable に指定されているものが同一グループのアイテムとして扱われるようになります。

このウィジェット変数の詳細に関しては下記ページで詳細を解説していますので、ウィジェット変数の役割やウィジェット変数の使い方等を知りたい方は下記ページをご参照ください。

ウィジェット変数の解説ページのアイキャッチ Tkinterの使い方:ウィジェット変数について解説【StringVar・BooleanVar・IntVar・DoubleVar】

チェックボタンメニューアイテムの場合は、チェックの ON / OFF の2つの状態が管理できれば良いので、add_checkbuttonvariable には tkinter.BooleanVar() で生成したウィジェット変数を指定すればよいです。

それに対し、ラジオボタンメニューアイテムの場合は、3つ以上を含む複数のアイテムのうちのどれが選択されているかを判別できるようにする必要があるので、他のウィジェット変数を指定することが多いと思います。例えば、メニューウィジェットの使い方 においては、 の3つのアイテムが選択されているときにはウィジェット変数に 'red''green''blue' の文字列をそれぞれセットするようにするため、これらのラジオボタンメニューアイテムを追加する時に実行する add_radiobuttonvariable には tkinter.StringVar() で生成したウィジェットを指定するようにしています。要は、アイテムが選択された時にセットしたい値に応じてウィジェット変数の種類を変更する必要があるので、この点には注意してください。

例えば下記のように add_checkbutton を実行すれば、追加されたチェックボタンメニューアイテムが ON のときは check_vTrue が、OFF の時は check_vFalse がセットされるようになります。また、check_v.get() によって check_v にセットされている値が取得できるため、そのチェックボタンメニューアイテムが ON / OFF のどちらであるかは print_checked 関数のような処理で判別することが可能となります。

variableの指定例
def print_checked():
    if check_v.get():
        print('チェックON')
    else:
        print('チェックOFF')

# 初期値がFalseのウィジェット変数生成
check_v = tkinter.BooleanVar(value=False)

# menu:メニューウィジェット
menu.add_checkbutton(
    # 略
    variable=check_v
)

また、追加されたチェックボタンメニューアイテムのチェックが ON / OFF それぞれの時にウィジェット変数にセットされる値は、後述の onvalueoffvalue で設定可能ですし、追加されたラジオボタンメニューアイテムが選択されているときにウィジェット変数にセットされる値は、後述の value で設定可能です。

onvalue / offvalue

onvalue は追加するチェックボタンメニューアイテムのチェックが ON のときにウィジェット変数にセットする値を、offvalue は追加するチェックボタンメニューアイテムのチェックが OFF のときにウィジェット変数にセットする値を設定するキーワード引数になります。

onvalueとoffvalueの説明図

これらはチェックボタンメニューアイテムに対する設定となるため、チェックボタンメニューアイテムを追加する add_checkbutton にのみ指定可能なキーワード引数となります。

cascade command check radio
× × ×

ウィジェット変数にセットできる値はウィジェット変数の種類によって異なります。また、ウィジェット変数は前述の variable で指定することになるため、onvalueoffvalue には「variable で指定するウィジェット変数にセット可能な値」を指定する必要があります。例えば variabletkinter.StringVar() で生成したウィジェット変数を指定するのであれば、onvalueoffvalue には文字列を指定する必要があることになります。

onvalue のデフォルト値は Trueoffvalue のデフォルト値は False です。そのため、これらを指定しない場合は、variabletkinter.BooleanVar() で生成したウィジェット変数を指定する必要があります。逆に言えば、variabletkinter.BooleanVar() で生成したウィジェット変数を指定してやれば、onvalueoffvalue の指定は不要となります。

例えば下記のように add_checkbutton を実行すれば、追加されたチェックボタンメニューアイテムのチェックが ON のときは check_v'ON' という文字列が、OFF の時は check_v'OFF' という文字列がセットされるようになります。ただし、check_v には文字列がセットされることになるため、check_v には tkinter.StringVar() で生成したウィジェット変数を指定する必要があります。また、check_v.get() によって check_v にセットされている値が取得できるため、そのチェックボタンメニューアイテムのチェックが ON / OFF のどちらであるかは print_checked 関数のような処理で判別することが可能となります。

onvalueとoffvalueの指定例
def print_checked():
    if check_v.get() == 'ON':
        print('チェックON')
    else:
        print('チェックOFF')

# 初期値が'OFF'のウィジェット変数生成
check_v = tkinter.StringVar(value='OFF')

# menu:メニューウィジェット
menu.add_checkbutton(
    # 略
    variable=check_v,
    onvalue='ON',
    offvalue='OFF'
)

value

value は、追加するラジオボタンメニューアイテムが選択されているときにウィジェット変数にセットする値を設定するキーワード引数になります。

value引数の説明図

value はラジオボタンメニューアイテムに対する設定となるため、ラジオボタンメニューアイテムを追加する add_radiobutton にのみ指定可能なキーワード引数となります。また、valuevariable とセットで指定する必要があります。

cascade command check radio
× × ×

onvalueoffvalue と同様に、value には「variable で指定するウィジェット変数にセット可能な値」を指定する必要があります。

variable を指定する場合は、add_radiobutton には必ず value も指定する必要があります。また、複数のラジオボタンメニューアイテムのうち、どれが選択中であるかをウィジェット変数にセットされる値から判別できるようにするためには、同じ variable を指定する add_radiobutton では、それぞれで異なる値を value に指定する必要があります。

例えば下記のように add_radiobutton を実行すれば、表示名が の3つのラジオボタンメニューアイテムが追加され、これらは同じ variable=color_v が指定されているため、同じグループのアイテムとした使われます。また、それぞれの value の指定により、 のアイテムが選択されると color_v'red' が、 のアイテムが選択されると color_v'green' が、 のアイテムが選択されると color_v'blue' がそれぞれセットされることになるため、print_selected 関数のように color_v.get で取得される値によって、選択中のアイテムが判別できることになります。

valueの指定例
def print_selected():
    if color_v.get() == 'red':
        print('赤が選択中')
    elif color_v.get() == 'green':
        print('緑が選択中')
    else:
        print('青が選択中')

# 初期値が'red'のウィジェット変数生成
color_v = tkinter.StringVar(value='red')

# menu:メニューウィジェット
menu.add_radiobutton(
    # 略
    label='赤',
    variable=color_v,
    value='red'
)

menu.add_radiobutton(
    # 略
    label='緑',
    variable=color_v,
    value='green'
)

menu.add_radiobutton(
    # 略
    label='青',
    variable=color_v,
    value='blue'
)

スポンサーリンク

indicatoron

indicatoron は、追加するチェックボタンメニューアイテムやラジオボタンメニューアイテムのチェックマークの表示の有無を設定するキーワード引数になります。

indicatoron引数の説明図

indicatoron は add_checkbuttonadd_radiobutton に指定可能なキーワード引数となります。

cascade command check radio
× ×

indicatoron には True or False を指定します。indicatoron のデフォルト値は True となります。

チェックボタンメニューアイテムに関しては ON の場合に、ラジオボタンメニューアイテムに関しては選択中の場合に、アイテムの左側にチェックマークが表示されるようになっていますが、indicatoron=False を指定することで、そのチェックマークを非表示にすることができます。

例えば下記のように add_checkbutton を実行すれば、追加されたチェックボタンメニューアイテムのチェックマークを非表示にすることができます。

indicatoronの指定例
# menu:メニューウィジェット
menu.add_checkbutton(
    # 略
    indicatoron=False
)

image

image は、追加するメニューアイテムの表示を画像に変更するキーワード引数になります。

image引数の説明図

image は全メソッドに対して指定可能なキーワード引数となります。

cascade command check radio

前述の通り、追加したメニューアイテムは label に指定した文字列で表示されることになります。ですが、image を指定することで、追加したメニューを文字列ではなく画像で表示することが可能となります。

labelimage の両方を指定した場合は、image が優先されて画像が表示されることになります。label に指定した文字列と image に指定した画像の両方を表示するようにしたい場合は、後述の compound 引数を指定する必要があります。

また、image の値には Tkinter の画像オブジェクトを指定する必要があります。この Tkinter の画像オブジェクトに関しては下記ページでまとめていますので、詳細は下記ページを参照してください。

Tkinterで画像を扱う方法の解説ページアイキャッチ Tkinter の使い方:PhotoImage・BitmapImageクラスで画像を扱う

例えば下記のように add_command を実行すれば、追加されたコマンドメニューアイテムが cat.png の画像として表示されることになります。

indicatoronの指定例
photo = tkinter.PhotoImage(
    file='cat.png',
)

# menu:メニューウィジェット
menu.add_command(
    # 略
    image=photo
)

compound

compound は、追加するメニューアイテムの表示を画像+文字列に変更するキーワード引数になります。

compound引数の説明図

compound は全メソッドに対して指定可能なキーワード引数となります。

cascade command check radio

compound を指定することで、追加するメニューアイテムを label に指定した文字列+ image に指定した画像で表示することができるようになります。

compound には下記の5つの値を指定することが可能です。

  • tkinter.TOPlabel に指定した文字列の上側に image に指定した画像を表示する
  • tkinter.BOTTOMlabel に指定した文字列の下側image に指定した画像を表示する
  • tkinter.LEFTlabel に指定した文字列の左側に image に指定した画像を表示する
  • tkinter.RIGHTlabel に指定した文字列の右側に image に指定した画像を表示する
  • tkinter.NONE:文字列 or 画像の一方のみを表示する(label と image の両方が指定されていれば image を優先)

基本的には、label に指定した文字列に対して image に指定した画像をどちら側に表示するのかを上記の値で指定することになります。例えば、tkinter.BOTTOM を指定すれば、label に指定した文字列の下側(ボトム側)に image に指定した画像が表示されることになります。

また、compound のデフォルト値は tkinter.NONE となります。そのため、compound を指定しない場合は、メニューアイテムは文字列 or 画像のどちらか一方で表示されることになります。

例えば下記のように add_command を実行すれば、追加されたコマンドメニューアイテムが 設定 という文字列+ cat.png の画像として表示されることになります。compoud=tkinter.BOTTOM を指定しているため、このコマンドメニューアイテムは 設定 という文字列の下側に cat.png の画像が配置された形で表示されることになります。

indicatoronの指定例
photo = tkinter.PhotoImage(
    file='cat.png',
)

# menu:メニューウィジェット
menu.add_command(
    # 略
    label='設定',
    image=photo,
    compoud=tkinter.BOTTOM
)

スポンサーリンク

accelerator

accelerator は、追加するメニューアイテムの項目名の横に追加で表示する文字列を設定するキーワード引数になります。

accelerator引数の説明図

accelerator は全メソッドに対して指定可能なキーワード引数となります。

cascade command check radio

accelerator には文字列を指定します。

この accelerator は各種メニューアイテムのショートカットキーを示すために利用されることが多いと思います(というか、それ以外に使い道が思いつかない…)。例えば、accelerator='(Alt+s)' を指定すれば、追加されるメニューアイテムの項目名の右側に (Alt+s) が表示され、そのアイテムのショートカットキーが Alt キーと s キーの同時押しであることをユーザーに示すことができるようになります。

ただし、この accelerator はショートカットキーの表示をするだけで、accelerator を指定しただけでショートカットキーが設定されるというわけではないので注意してください。ショートカットキーとして機能させるためには、bind メソッドや invoke メソッドの実行が必要となります。このあたりは後述の invoke で説明します。

例えば下記のような処理を実行すれば、add_command で追加されたメニューアイテムの項目名 設定 の右に (Alt+s) が表示されるようになります。

acceleratorの指定例
# menu:メニューウィジェット
menu.add_command(
    # 略
    label='設定',
    accelerator='(Alt+s)'
)

state

state は、追加するメニューアイテムの状態を設定するキーワード引数となります。例えば、そのメニューアイテムを無効化(クリック不可)にするようなことも可能です。

state引数の説明図

state は全メソッドに対して指定可能なキーワード引数となります。

cascade command check radio

state には下記の3つの値が指定可能ですが、おそらくメニューアイテムに関しては tkinter.NORMALtkinter.ACTIVE を指定した場合は、両方とも同じ状態(有効状態)になると思います。

  • tkinter.NORMAL:有効化
  • tkinter.DISABLED:無効化
  • tkinter.ACTIVE:有効化?

また、tkinter.DISABLED で無効化したメニューアイテムの文字色は、メニューウィジェット生成時に disabledforeground を指定することで変更可能です。詳細に関しては disabledforeground を参照してください。

例えば下記のように add_cascade を実行すれば、追加されたメニューアイテムはクリック不可となります。

stateの指定例
# menu:メニューウィジェット
menu.add_cascade(
    # 略
    state=tkinter.DISABLED
)

background

background に関してはメニューウィジェットの設定の方で説明しましたので、詳細に関しては background を参照してください。 

background は全メソッドに対して指定可能なキーワード引数となります。

cascade command check radio

スポンサーリンク

foreground

foreground に関してもメニューウィジェットの設定の方で説明しましたので、詳細に関しては foreground を参照してください。 

foreground は全メソッドに対して指定可能なキーワード引数となります。

cascade command check radio

activebackground

activebackground に関してもメニューウィジェットの設定の方で説明しましたので、詳細に関しては activebackground を参照してください。 

activebackground は全メソッドに対して指定可能なキーワード引数となります。

cascade command check radio

activeforeground

activeforeground に関してもメニューウィジェットの設定の方で説明しましたので、詳細に関しては activeforeground を参照してください。 

activeforeground は全メソッドに対して指定可能なキーワード引数となります。

cascade command check radio

スポンサーリンク

selectcolor

selectcolor に関してもメニューウィジェットの設定の方で説明しましたので、詳細に関しては selectcolor を参照してください。 

selectcolor は、チェックマークの表示されるチェックボタンメニューアイテムを追加する add_checkbuttonadd_radiobutton に対してのみ指定可能なキーワード引数となります。

cascade command check radio
× ×

font

font に関してもメニューウィジェットの設定の方で説明しましたので、詳細に関しては font を参照してください。 

font は全メソッドに対して指定可能なキーワード引数となります。

cascade command check radio

Menu クラスのメソッド

最後に Menu クラスに用意されたメソッドについて紹介していきたいと思います。

ここでは、Menu クラス特有のメソッド&私が動作を理解している下記の4種類のメソッドのみを紹介させていただきます。

スポンサーリンク

add_xxxxx

まず、ここまでにも紹介してきた下記の5つのメソッドが挙げられます。

  • add_cacscade
  • add_command
  • add_checkbutton
  • add_radiobutton
  • add_separator

これらは、メニューウィジェット(メニューグループ)の末尾に各種要素を追加するメソッドとなります。なので、これらの要素は実行した順序で上から順に表示されることになります。

insert_xxxxx

それに対し、下記の5つのメソッドは、追加する位置を指定して各種要素をメニューグループに追加するメソッドとなります。

  • insert_cacscade
  • insert_command
  • insert_checkbutton
  • insert_radiobutton
  • insert_separator

これらの第1引数(or index 引数)に整数を指定することで、メニューグループの好きな位置に各種要素を追加することが可能です。この引数には 0 以上の整数を指定する必要があり、メニュグループの一番上側が 0 に対応しています。

insert_xxxxxメソッドの説明図

ただし、分離実行アイテムの上側には要素追加することは不可のようなので、その点には注意してください。

その他の引数に関しては add_xxxxx と同様であるため、詳細に関しては add_xxxxx のメソッド を参照してください。

post

post メソッドは、任意の座標にメニューグループを表示するメソッドとなります。

これを利用して、例えば右クリックメニューを表示するようなことが可能となります。

postメソッドの説明図

post メソッドには第1引数(or x 引数)にメニューグループを表示する x 座標、第2引数(or y 引数)にメニューグループを表示する y 座標を指定して実行します。

postメソッドの引数
メニューウィジェット.post(x 座標, y 座標)

例えば、下記のようなスクリプトを実行すれば、右クリック実行時に menu が表示されるようになります。環境によっては、右クリックが <ButtonPress-3> と対応していない可能性があるので、必要に応じてこの部分は、あなたの使用環境に合わせて修正してください。

右クリックメニューの表示
import tkinter

def right_menu(event):
    # menuをクリックされた位置に表示
    menu.post(event.x_root, event.y_root)

def file_open():
    print('file_open')

def file_save(x):
    print('file_save')

# メインウィンドウを作成
app = tkinter.Tk()
app.geometry('400x300')

# メニューグループを作成
menu = tkinter.Menu(
    app,
)

menu.add_command(label='開く', command=file_open)
menu.add_command(label='保存', command=file_save)

# 右クリック時に実行する関数をbind
app.bind('<ButtonPress-3>', right_menu)

# メインループ
app.mainloop()

ちなみに、クリック等のイベントに関しては下記ページでまとめていますので、イベントに関して知りたい方は別途下記ページを参照してください。

イベント処理解説ページのアイキャッチ Tkinterの使い方:イベント処理を行う

スポンサーリンク

invoke

invoke は、メニューアイテムのクリックを行うメソッドになります。

これを利用することで、各種メニューアイテムに対するショートカットキーを設定することが可能です。

invokeメソッドの説明図

invoke メソッドには第1引数(or index 引数)にクリックしたいメニューグループ内の位置を指定します。この位置は、各種メニューグループに追加されたメニューアイテム(分離実行アイテムを含む)に対して上から順に割り当てられた整数で、一番上が 0 となります。

invokeメソッドの引数
メニューウィジェット.invoke(クリックしたい位置)

例えば、下記のようなスクリプトを実行すれば、Alt キーと o キーの同時押しによって項目名が 開く のメニューアイテムがクリックされることになり、print('file_open') が実行されることになります。また、Alt キーと c キーの同時押しによって項目名が チェック のメニューアイテムがクリックされることになり、この項目のチェックの ON / OFF が切り替わることになります。

ショートカットキーの設定
import tkinter

def click_open(event):
    sub_menu.invoke(0)

def click_check(event):
    sub_menu.invoke(1)

def file_open():
    print('file_open')


# メインウィンドウを作成
app = tkinter.Tk()
app.geometry('400x300')

# メニューグループを作成
menu = tkinter.Menu(
    app,
)

sub_menu = tkinter.Menu(
    menu,
    tearoff=False
)

# メインメニューを設定
app.config(menu=menu)


menu.add_cascade(label='サブメニュー', menu=sub_menu)

sub_menu.add_command(label='開く', command=file_open, accelerator='(Alt+o)')
sub_menu.add_checkbutton(label='チェック', accelerator='(Alt+c)')

# Alt+oが押された時に実行する関数をbind
app.bind('<Alt-o>', click_open)

# Alt+cが押された時に実行する関数をbind
app.bind('<Alt-c>', click_check)

# メインループ
app.mainloop()

上記の例のように、各メニューアイテムに割り当てたショートカットキーの表示に関しては、add_xxxxx に対して accelerator 引数を利用して表示するのが良いと思います。

まとめ

このページでは、Tkinter のメニューウィジェットについて解説しました!

このメニューウィジェットを利用することで、Tkinter で開発するアプリにメニューバーを表示することができるようになります。また、右クリックメニュー等も実現することが可能です。

メニューウィジェットは「グループ」であることを意識すると使い方が分かりやすくになると思います。このグループにアイテムだけでなくグループを追加することで、複数の階層のメニューバーを実現することが可能です。

是非、ご自身でメニューバー付きのウェブアプリを開発し、その動きを確認しながらメニューウィジェットへの理解を深めてみてください!

オススメ参考書(PR)

Tkinter に興味がある方には下記のPythonでつくる ゲーム開発 入門講座がオススメです。

Tkinter をゲーム開発を通して「楽しく学ぶ」ことができます。Python 入門者、Tkinter 入門者の方にオススメです。

同じカテゴリのページ一覧を表示