機械系エンジニアの備忘録

20代独身社会人。仕事では機械・機構の研究開発を行っているエンジニアが、自分の専門分野ではないpythonを扱って楽しむブログです。

MENU

【python】【tkinter】【初心者】メニュバーを作り、一つのウインドでタブを操作するように複数のアプリを切り替える

メニューバーを作って、タブを操作するようにアプリを切り替えられるようにする

■はじめに

これまでtkinterを使って様々なアプリもどきを作ってきました。

stjun.hatenablog.com

stjun.hatenablog.com

stjun.hatenablog.com

stjun.hatenablog.com

今回はこれらのアプリを簡単に切り替えられるようにメニューバーを作成し、タブを操作するように複数のアプリを切り替えられるようにしてみます。 

 

■コード、実行結果

import tkinter as tk
import tkinter.ttk as ttk

def change_page(page):
    page.tkraise()


#ウインドの作成
root=tk.Tk()

#menuバーをrootに作る
menu=tk.Menu(root)
#個別のmenuを作る
menu_1=tk.Menu(menu,tearoff=False)
#menuを選択した時に出てくるドロップリストを作る
menu_1.add_command(label="ラジオボタン",command=lambda :change_page(frame_all_1))
menu_1.add_command(label="スクロールバーとリストボックス",command=lambda :change_page(frame_all_2 ))
#menuバーに個別のmenuを足す
menu.add_cascade(label="メニュー",menu=menu_1)

menu_2=tk.Menu(menu,tearoff=False)
menu_2.add_command(label="ラジオボタン",command=lambda :change_page(frame_all_1))
menu_2.add_command(label="スクロールバーとリストボックス",command=lambda :change_page(frame_all_2 ))
menu.add_cascade(label="ファイル",menu=menu_2)

#ウィジェット作成
frame_all_1 = ttk.Frame(root)
frame_all_1.grid(row=0, column=0, sticky="nwse")
#フレームの作成
#フレーム1(左上)
frame=tk.LabelFrame(frame_all_1,labelanchor="nw",text="ラジオボタン1",foreground="green")
frame.grid(row=0,column=0)
#フレーム2(右上)
frame_1=tk.LabelFrame(frame_all_1,text="ラジオボタン2",foreground="green")
frame_1.grid(row=0,column=1)
#フレーム3(下)
frame_2=tk.LabelFrame(frame_all_1,text="その他",foreground="green")
frame_2.grid(row=1,columnspan=2,sticky="we")

#ラジオボタンの作成(フレーム1に作成)
var=tk.IntVar()
var.set(0)
radio_0=tk.Radiobutton(frame,value=0,variable=var,text="ラジオボタン0")
radio_0.pack()
radio_1=tk.Radiobutton(frame,value=1,variable=var,text="ラジオボタン1")
radio_1.pack()
radio_2=tk.Radiobutton(frame,value=2,variable=var,text="ラジオボタン2")
radio_2.pack()
radio_3=tk.Radiobutton(frame,value=3,variable=var,text="ラジオボタン3")
radio_3.pack()

#ラジオボタンの作成(フレーム2に作成)
radio_4=tk.Radiobutton(frame_1,value=4,variable=var,text="ラジオボタン4")
radio_4.pack()
radio_5=tk.Radiobutton(frame_1,value=5,variable=var,text="ラジオボタン5")
radio_5.pack()
radio_6=tk.Radiobutton(frame_1,value=6,variable=var,text="ラジオボタン6")
radio_6.pack()
radio_7=tk.Radiobutton(frame_1,value=7,variable=var,text="ラジオボタン7")
radio_7.pack()

#テキストの作成(フレーム3に作成)
text_str=tk.StringVar()
text_str.set("ボタンを押して下さい")
text=tk.Label(frame_2,textvariable=text_str)
text.pack()

#ボタンを押したときに動作する関数
def check():
    text_check=var.get()
    text_str.set(str(text_check))

#ボタンの作成(フレーム3に作成)
Button=tk.Button(frame_2,text="判定",command=check)
Button.pack()


frame_all_2 = ttk.Frame(root)
frame_all_2.grid(row=0, column=0, sticky="nwse")
#フレームの作成
frame_3=tk.Frame(frame_all_2 )
frame_3.grid(row=0,sticky="we")

frame_button=tk.Frame(frame_all_2)
frame_button.grid(row=1,sticky="we")

#スクロールバーの作成
scroll=tk.Scrollbar(frame_3)

#スクロールバーの配置を決める
scroll.pack(side=tk.RIGHT,fill="y")

#データ
list_value=tk.StringVar()
list_value.set(["Aさん","Bさん","Cさん","Dさん","Eさん","Fさん","Gさん","Hさん","Iさん","Jさん","Kさん","Lさん"])

#リストボックスの作成
#selectmodeの種類(single:1つだけ選択できる、multiple:複数選択できる、extended:複数選択可能+ドラッグでも選択可能)
listbox=tk.Listbox(frame_3,height=8,listvariable=list_value,selectmode="single",yscrollcommand=scroll.set)
listbox.pack()

#部品の動きをスクロールバーに反映させる
scroll["command"]=listbox.yview

#テキストの作成
text_str=tk.StringVar()
text_str.set("ボタンを押して下さい")
text=tk.Label(frame_button,textvariable=text_str)
text.grid(row=0,columnspan=3)

#ボタンを押したときに動作する関数
def text_check():
    text_check=listbox.curselection()
    text_str.set(listbox.get(text_check))

#ボタンの作成
Button_check=tk.Button(frame_button,text="判定",command=text_check)
Button_check.grid(row=1,column=0)

def all_select():
    listbox.select_set(0,tk.END)
Button_allselect=tk.Button(frame_button,text="全選択",command=all_select)
Button_allselect.grid(row=1,column=1)

def all_clear():
    listbox.select_clear(0,tk.END)
Button_allclear=tk.Button(frame_button,text="全クリア",command= all_clear)
Button_allclear.grid(row=1,column=2)

#frame1を上位層にする
frame_all_1.tkraise()

root["menu"]=menu
#ウインドの表示
root.mainloop()

実行すると以下の画像が表示されます。

f:id:stjun:20191218225748p:plain

上部のメニューバーの「メニュー」をクリックすると、このように「ラジオボタン」と「スクロールバーとリストボックス」の二つのアプリが出てきます。(※今回はこの二つのアプリだけ組み込んでみました)

f:id:stjun:20191218225844p:plain

ここで「スクロールバーとリストボックス」をクリックするとアプリが切り替わります。

f:id:stjun:20191218230045p:plain

f:id:stjun:20191218230226p:plain

またメニューバーから「ラジオボタン」を押すとラジオボタンのアプリに戻ります。

f:id:stjun:20191218230328p:plain

f:id:stjun:20191218230349p:plain

なおメニューバーの欄に「ファイル」という名前のタブも作ってみました。

今回は大変だったので中身は「メニュー」タブと同じにしてあります。

f:id:stjun:20191218230602p:plain

 

 

■買って良かったもの紹介

最近読んだ本です。

投資信託についてあまり知らなかったので良い勉強になりました。

はじめての人のための3000円投資生活

はじめての人のための3000円投資生活

  • 作者:横山光昭
  • 出版社/メーカー: アスコム
  • 発売日: 2016/06/24
  • メディア: 単行本(ソフトカバー)
 

 

■説明

2019/12/18 工事中、仕事が忙しいので落ち着いたら説明文を追加したいと思います。 

2020/01/03 説明文を追記 

1. メニューバーの作成方法

メニューバーを作るときの基本コードは以下になります。

下のコードを覚えるかコピペして、必要に応じてメニューの数などを増やしていくと良いと思います。

各コードがどんな役割を持っているかもコメントに書きました。

import tkinter as tk

#ウインドの作成
root=tk.Tk()

#menuバーをrootに作る
menu=tk.Menu(root)
#個別のmenuを作る
menu_1=tk.Menu(menu,tearoff=False)
#menuを選択した時に出てくるドロップリストを作る
menu_1.add_command(label="小メニュー1",command=lambda :change_page(frame_all_1))
menu_1.add_command(label="小メニュー2",command=lambda :change_page(frame_all_2 ))
#menuバーに個別のmenuを足す
menu.add_cascade(label="大メニュー",menu=menu_1)

#ウインドにmenuバーを表示
root["menu"]=menu
#または root.comfig(menu=menu)でもok

#ウインドの表示
root.mainloop()

実行結果は以下になります。

f:id:stjun:20200103173002p:plain

ここで四行目の、

menu_1=tk.Menu(menu,tearoff=False)

のtearoff=Falseですが、こちらをFalseにしなかった場合に下記のようにメニューの上部に切り取り線が現れ、クリックすると切り取ることが出来るようになります。

f:id:stjun:20200103173326p:plainf:id:stjun:20200103173248p:plain

今回は切り取られたくないのでFalseにしていますが、必要に応じてTrueにするか決めて下さい。

次に5行目、6行目の、

menu_1.add_command(label="小メニュー1",command=lambda :change_page(frame_all_1))
menu_1.add_command(label="小メニュー2",command=lambda :change_page(frame_all_2 ))

の中のcomand=lambda:~~~の部分ですが、lambaは関数を定義するために使用しています。詳しくは以下の過去記事をご覧ください。簡単に言うと、各メニューごとに個別の関数を作っても良いのですが、1つの関数で簡潔に書きたかったのでこのような書き方をしました。こんなものかくらいに思って頂ければ十分だと思います。

stjun.hatenablog.com

 またどうやって画面を切り替えているかを簡単に図解したのが以下になります。

f:id:stjun:20200103174525j:plain

「フレーム名」.tkarise()で一番前に任意のフレームを持ってくることができるので、この動作をchange_page()という関数にして、メニューバーを押すと関数change_page()が呼び出されて任意のフレームが一番前に来るようにしています。

今回は2つのフレーム「frame_all_1」と「frame_all_2」だけですが、これが3つ以上になっても基本は同じです。

 

■おわりに

いかがだったでしょうか。メニューバーを入れると一気にちゃんとしたアプリっぽくなります。