弊サイト「電脳世界」の著書・技術同人誌『Pythonの2歩目でGUIアプリ制作をやるならTkinter』の試し読み記事として、全120ページのうち40ページを無料で公開しています。
本著はPythonプログラミングの基礎をすでに身につけた方のなかで、次のステップとして GUI アプリケーションの制作に進みたい方に向けて書き上げたものです。
※本記事は書籍の内容をWebサイトでの公開用にフォーマットし直しているため枠や色合い、文章の改行部分など書籍とは少々異なる部分がございます。
第1章 Tkinterとは
この章では本著での GUI アプリケーション制作に使用するTkinter というツールキットの概要と周辺知識について学びます。
1.1 Tkinterとはなにか
TkinterはPythonの標準ライブラリに含まれている、GUI(グラフィックユーザーインターフェース)を構築・操作するためのモジュールです。
厳密に言えばスクリプト言語TclのGUIツールキットであるTkをPythonから操作するためのインターフェースで、TkinterというのはTk interfaceの略称です。
Tkはクロスプラットフォームのツールキットのため、ほとんどのUnixプラットフォームのほか、Windows、MacOSのシステム上でも利用できます。
PythonでGUIを作成するツールはTkinterの他にもPySimpleGUI、Pygame、Kivy、PyQtなどが挙げられますが、その中でもTkinterはPythonの標準ライブラリに含まれていることもあり
- インストール不要ですぐに始められる
- 困った時に情報を探しやすい
といった点から初心者向けのGUIアプリ制作ツールとしておすすめできます。
複雑なことをやろうとすると骨が折れますが、基盤を作るだけなら凄まじく簡単で、例えばウィンドウを表示するだけなら次のようにたった3行のコードでできてしまいます。
import tkinter root = tkinter.Tk() root.mainloop()
1.2イベント駆動方式
GUIアプリケーションでは、ユーザーからの入力やシステムの状態変化など、ある出来事をきっかけに処理を実行します。
例えば
- ユーザーがマウスを左クリックした
- キーボードの特定のキーが押された
といった具合です。
この出来事をイベントと呼び、イベントをきっかけにしてプログラムが起動されることをイベントドリブン(イベント駆動)と呼びます。
イベントドリブン型のアプリケーションは一般に次のようなメインルーチン(実行中に繰り返し処理されるメイン機能)を持っています。
- 初期化
- イベントを取得する
- イベントの種類に応じて処理を振り分ける
- 2に戻る
2から4をイベントループと呼び、アプリケーションはユーザーからの入力などのイベントを待っています。
そして3の処理に対応する機能がバインディングです。
バインディングはウィンドウでイベントが発生したときに、それに応じて予め定義しておいた処理を実行します。このときに呼び出される処理をイベントハンドラやコールバック関数と呼びます。
このようにGUIアプリケーションとしての最低限の機能はPythonとTkinterが面倒を見てくれるので、私たちはアプリケーション固有の処理をプログラミングするだけで済みます。
1.3 Python / Tkinter でGUIアプリを作るときのざっくりとした手順
学習に入る前に、Python / Tkinter でGUIアプリケーションを作る際のざっくりとした手順を知っておきましょう。
- トップレベルのウィンドウ(メインウィンドウ)を作る
- ウィジェットを作成してウィンドウに配置する
- イベントループを開始する処理を書く
- 必要に応じてコールバック関数を作る
まずGUIアプリの大枠となるメインウィンドウを作り、その中にウィジェットという画面を構成する部品オブジェクトを配置。イベントループを開始すれば見た目は作ったとおりに表示されます。
あとはどのようなイベントを受け取った時に、どの処理を返すのかという処理を作ればGUIアプリの完成です。
第2章 ウィジェットを使ってみよう
この章ではTkinterに予め用意されている各種ウィジェットについて知り、実際に使ってみましょう。また、複数のウィジェットを内包して階層構造を作るためのフレームウィジェットについても学んでいきます。
2.1 TkinterでHelloWorld
2.1.1 ウィンドウの作成
まずはアプリケーションのウィンドウを作ってみましょう。下記のコードを記述したPythonプログラムファイルを作成して実行してみて下さい。
※ファイル名はtkinter.pyとするとAttributeErrorとなるので他の名前にしておきましょう。
import tkinter # tkinterモジュールを読み込み root = tkinter.Tk() # rootインスタンスを作成 # ウィンドウの設定 root.title("ウィンドウのタイトル") # ウィンドウのタイトルを指定 root.geometry("400x300") # ウィンドウサイズの指 root.mainloop() # rootインスタンスのmainloopメソッドを呼び出し
上記のようなウィンドウが表示されます。
あとはこのroot要素の中に各ウィジェットを作成していけばテキストや画像の表示はもちろん、ボタンやチェックボックス、スクロールバー、プログレスバーなんかも簡単に作れてしまいます。
2.1.2 Hello World
ということでまずはお約束のHello Worldを表示してみましょう。テキストや画像を表示するだけだればラベル(Label)というウィジェットが便利です。
import tkinter as tk root = tk.Tk() # ウィンドウの設定 root.title("ウィンドウのタイトル") root.geometry("400x300") # ウィンドウサイズの指定 #ラベルウィジェット msg = tk.Label(text="Hello World") # ラベルウィジェットに表示したい文字を渡してインスタンスを生成 msg.pack() # インスタンスのpackメソッドを実行 root.mainloop() # rootインスタンスのmainloopメソッドを呼び出し
毎回モジュール名を書いていては面倒なので import tkinter as tk としてtkinterをtkという名前で呼び出せるようにします。
ウィジェットを配置する方法はいくつかあるので後述しますが、今回は単純な配置なのでpackメソッドを使っています。
Hello World の表示ができました。まだウィンドウの大きさや文字の大きさ、文字の配置位置など色々違和感はありますが、それはこれから各ウィジェットの項で学んでいきましょう。
2.2 階層構造とフレームウィジェット
2.2.1 Tkinterにおけるウィジェットの階層構造
Tkinterではウィジェットは階層構造を構成するように配置します。
rootインスタンスにそのまま各ウィジェットを配置していくこともできますが、フレームウィジェットで各ウィジェットをまとめてグループ化することでプログラムをフレーム単位でモジュール化することができ、フレームを乗せ換えることでアプリケーションの画面を切り替えることもできるようになります。
また、詳しくは後述しますが、フレームで各ウィジェットを囲ってあげることでレイアウトの自由度も高くなります。
2.2.2 フレームウィジェットとは
フレームウィジェット自体はほとんど何をするわけでもありませんが、他のウィジェットをまとめて配置するためのコンテナとして働きます。
Frameインスタンスを作成する際は次のオプション引数を指定することができます。
属性 | 説明 | 値 |
---|---|---|
bg or background | 背景の色を指定します | red,blue,grayなど |
bd or borderwidth | ボーダーの幅を指定します | ピクセル単位の数値 |
relief | ボーダー部分の浮き彫りを指定します | flat,raised,sunken,groove,ridge |
width | 幅をピクセル単位で指定します | ピクセル単位の数値 |
height | 高さをピクセル単位で指定します | ピクセル単位の数値 |
フレームウィジェットを作成する際は第一引数に親ウィジェットを指定します。
実際に親要素にルートインスタンスを指定してフレームウィジェットを作成・配置してみましょう。
import tkinter as tk root = tk.Tk() # ウィンドウの設定 root.title("ウィンドウのタイトル") root.geometry("400x300") # フレームの作成 frame1 = tk.Frame( # frame1インスタンスを作成 root, # 親要素を指定 background="gray", # 背景色を指定 borderwidth=5, # ボーダーの幅を指定 relief="sunken", # ボーダーの浮き彫りを指定 width=400, # 幅をピクセル単位で指定 height=300, # 高さをピクセル単位で指定 ) frame1.pack() # frame1インスタンスを配置 root.mainloop() # メインループの開始
実行結果は次のとおりです。
実際の例としてフレームウィジェットの中にラベル、エントリー、ボタンの各ウィジェットを配置してみましょう。各ウィジェットについてはこのあと詳しく解説するので、今はどういう構造になっているかだけ気にして見て下さい。
また、Tkinterを使ったGUI制作では先ほどのように手続き型で書いていくこともできるのですが、Tkinterを含めPythonのGUIアプリは次のようにフレームウィジェットで導出クラスを定義してオブジェクト指向で書くのが一般的です。
import tkinter as tk # tk.Frameを継承したFrame1クラスを作成 class Frame1(tk.Frame): def __init__(self, master=None): # コンストラクタを定義 super().__init__(master) # 継承元クラス(tk.Frame)のコンストラクタを呼び出し #ウィンドウの設定 master.title("ウィンドウのタイトル") master.geometry("400x300") # 幅と高さを指定 # フレームの設定 self.config(bg="whitesmoke") # 背景色を指定 self.propagate(False) # フレームのpropagate設定 (この設定がTrueだと内側のwidgetに合わせたフレームサイズになる) # 実行内容 self.pack() # フレームを配置 self.create_widget() # 下記で定義しているcreate_widget関数を実行 #create_widget関数を定義 def create_widget(self): # ラベルを作成 self.label1 = tk.Label(self.master, text="これはラベルです") self.label1.pack() # エントリーを作成 self.entry1 = tk.Entry(self.master) self.entry1.insert(tk.END, "これはエントリーです") self.entry1.pack() # ボタンを作成 button1 = tk.Button(self.master, text="これはボタンです") button1.pack() if __name__ == "__main__": # このファイルが直接実行されている場合の処理 root = tk.Tk() # rootインスタンスを生成 f1 = Frame1(master=root) # Frame1クラスからf1インスタンスを生成 f1.mainloop() # メインループの開始
※厳密にはcreate_widgetは作成したFrame1クラスのメソッドなのですが、これで進めると後々の説明がわかりにくくなってしまったため、本著では便宜上自作したものを関数、Tkinter側で予め用意されているものをメソッドと呼ぶことにします。
見た目上はラベル、エントリー、ボタンの各ウィジェットをそのまま配置したのと変わりませんが、このコードではそれらのウィジェットはFrame1という1つのフレームにまとめられているため効率的に管理・運用できます。
2.2.3 フレームを入れ子にする
フレームが1つだけだとわかりにくいので、フレームの中にフレームを2つ作成して、さらに各フレームにウィジェットを配置という入れ子形式にしてみましょう。
import tkinter as tk # tk.Frameを継承したApplicationクラスを作成 class Application(tk.Frame): def __init__(self, master=None): super().__init__(master, width=200, height=150) # ウィンドウの設定 self.master.title("ウィンドウのタイトル") # 実行内容 self.pack() # メインフレームを配置 self.create_widget() # create_widget関数を実行 #create_widget関数を定義 def create_widget(self): # 1つ目のフレーム frame1 = tk.Frame(self.master, relief=tk.RIDGE, bd=2) # tk.Frameクラスからframe1インスタンスを生成 list1 = [("A", "lightskyblue"), ("B", "khaki"), ("C", "yellowgreen"), ("D", "hotpink")] for text, color in list1: label=tk.Label(frame1, text=text, bg=color, font=("20")) # labelウィジェットを作成 label.pack(side=tk.LEFT) # labelウィジェットを配置 frame1.place(relx=0.1, rely=0.1) # frame1フレームを配置 # 2つ目のフレーム frame2 = tk.Frame(self.master, relief=tk.RIDGE, bd=2) # tk.Frameクラスからframe2インスタンスを生成 list2 = [("A", "lightskyblue"), ("B", "khaki"), ("C", "yellowgreen"), ("D", "hotpink")] for i, (text, color) in enumerate(list2): label=tk.Label(frame2, text=text, bg=color, font=("20")) # labelウィジェットを作成 label.grid(row=i//2, column=i%2) # labelウィジェットを配置 frame2.place(relx=0.6, rely=0.5) # frame2フレームを配置 if __name__ == "__main__": root = tk.Tk() app = Application(master=root) app.mainloop()
実行結果は次のとおりです。
このコードではメインフレームであるApplicationの中にframe1とframe2という2つのフレームを含み、frame1とframe2はそれぞれ4つのラベルウィジェットを含んでいます。
このように各ウィジェットをフレームで包んであげることで、frame1インスタンスだけを削除したり、移動したりといった管理・運用が可能になります。これがコンテナであるフレームウィジェットの役割です。
2.3 ラベルウィジェット
文字列の表示
ラベルウィジェット(Label)はTkinterのウィジェットクラスの1つで、文字や画像を表示することができます。まずは文字を表示してみましょう。
Tkinterではウィジェットクラスから個別のインスタンスを生成して配置するには次にように記述します。
import tkinter as tk # tk.Frameを継承したApplicationクラスを作成 class Application(tk.Frame): def __init__(self, master=None): super().__init__(master) # ウィンドウの設定 self.master.title("ウィンドウのタイトル") # 実行内容 self.pack() self.create_widget() #create_widget関数を定義 def create_widget(self): # label1ウィジェットを作成 self.label1 = tk.Label(self.master,text="表示したい文字列") # label1に表示したい文字を渡してインスタンスを生成 self.label1.pack() # label1ウィジェットを配置 if __name__ == "__main__": root = tk.Tk() app = Application(master=root) app.mainloop()
実行結果は次のとおりです。
オプション引数であるtextに表示したい文字列を渡し、インスタンスを作成、配置するだけです。
これくらいであればわざわざcreate_widget関数を作って処理を分けなくてもいいのですが、今後の説明をわかりやすくするために処理を分けておきます。
2.3.2 画像の表示
次は画像を表示してみましょう。Labelウィジェットで画像を表示したい場合は、Labelインスタンス生成時のimage引数に表示したい画像へのパスを指定します。
試しに先ほどのコードに新たに画像を含むlabel2ウィジェットを追加してみましょう。
毎回全て記述しているとコードが長くなりすぎて見づらいので、create_widget関数の中身だけ記述します。
# create_widget関数を定義 def create_widget(self): # label1ウィジェットを作成 msg = "うへっへへへうへへへへへ\nでへへェェうへへェェうヒィッ\nうひうひうひうはァッ\nでへっでへっどぅひひひひひ\nふっふふはっひひお\nへおへおへへェェッ" self.label1 = tk.Label(self.master, text=msg, font="24") self.label1.pack(side="right") # label2ウィジェットを作成 self.icon = tk.PhotoImage(file="img/denchan.png") # 画像のパスをicon変数に代入 self.label2 = tk.Label(self.master, image=self.icon, bg="white") # image引数に表示したい画像のパスを指定してインスタンスを生成 self.label2.pack(side="left") # label2ウィジェットを配置
実行結果は次のとおりです。
ラベルウィジェットで使えるオプション引数
ラベルウィジェットでも、フレームウィジェットの時と同様、オプション引数を使用することができます。
属性 | 説明 | 値 |
---|---|---|
anchor | テキストを配置する位置を指定します |
tk.CENTER(中央) tk.W(左寄せ) tk.E(右寄せ) tk.N(上寄せ) tk.S(下寄せ) tk.NW(左上) tk.SW(左下) tk.NE(右上) tk.SE(右下) |
font | テキストを表示する際のフォントの種類や大きさを指定します | フォント名、文字の大きさ(数値)など |
fg or foreground | フォントの色、または bitmap の色を指定します | |
justify | テキストが複数行にわたる場合、左寄せ、右寄せ、中央寄せを指定します | |
padx | 縁とテキストとの間の横の余白 | 数値(ピクセル単位) |
pady | 縁とテキストとの間の縦の余白 | 数値(ピクセル単位) |
text | 表示する文字列を指定します | 任意の文字列 |
textvariable | StringVar を指定。変化する文字列を表示するとき使用します。 | 変数名 |
ここに書いたもの以外にフレームウィジェット同様widthやheightなども使用することができますが、例えばwidthはフレームの場合ピクセル単位の数値で指定していましたが、ラベルの場合文字数単位での指定となっていたり指定する値が異なることがあるため注意が必要です。(ピクセル単位に統一してくれればいいのに…)
試しにいくつかのオプションを使って先ほどのコードを変更してみましょう。
# create_widget関数を定義 def create_widget(self): # label1ウィジェットを作成 msg = "うへっへへへうへへへへへ\nでへへェェうへへェェうヒィッ\nうひうひうひうはァッ\nでへっでへっどぅひひひひひ\nふっふふはっひひお\nへおへおへへェェッ" self.label1 = tk.Label(self.master, text=msg, fg="white", font=("MSゴシック", "20", "bold"), bg="black") self.label1.pack(side="right") # label2ウィジェットを作成 self.icon = tk.PhotoImage(file="img/denchan.png") self.label2 = tk.Label(self.master ,image=self.icon, bg="white") self.label2.pack(side="left")
実行結果は次のとおりです。
このようにオプション引数を使い分けることで文字や画像を自由自在に表示できます。
2.4 ボタンウィジェット
ボタンウィジェットは文字や画像を表示し、その名の通りユーザーがマウスでクリックすることでそのボタンを「オン」にすることができます。
ボタンウィジェットの作成・配置
ボタンを生成して配置するには他のウィジェット同様次のように記述します。
今回もcreate_widget関数の中身だけ記述するので、それ以外の部分(アプリケーションフレームの作成やメインループの開始)はラベルウィジェットのコードをご参照下さい。
# create_widget関数を定義 def create_widget(self): # label1ウィジェットを作成 self.label1 = tk.Label(self.master, text="「スイッチ」を押させるなーーーーッ") self.label1.pack() # button1ウィジェットを作成 self.button1 = tk.Button(self.master ,text="いいや!限界だ押すね!") # button1に表示したい文字を渡してインスタンスを生成 self.button1.pack() # button1ウィジェットを配置
ラベルウィジェットとボタンウィジェットを1つずつ作成・配置したコードです。
実行結果は次のとおりです。
このように立体感のあるボタンを作成することができます。ボタンは押すと凹みますが、今はまだ押した時の処理を作っていないためそれ以上何も起こりません。
2.4.2 ボタンが押された時の処理
ボタンを押した時の処理を定義し、ボタンが押された時に呼び出されるよう紐づけてみましょう。
# create_widget関数を定義 def create_widget(self): # label1ウィジェット self.label1 = tk.Label(self.master, text="「スイッチ」を押させるなーーーーッ") self.label1.pack() # button1ウィジェット self.button1 = tk.Button(self.master, text="いいや!限界だ押すね!", command=self.button1_clicked) # command引数にbutton1_clicked関数を渡す self.button1.pack() # button1ウィジェットを配置 # button1をクリックした時の処理 def button1_clicked(self): app.quit() # メインループを終了
ボタンが押された時の処理をbutton1_clicked関数として定義しています。quitメソッドは全てのウィジェットに予め用意されているユニバーサルメソッドの1つで、メインループを終了(アプリを終了)します。
そして、この処理をボタンに紐づけるために、button1インスタンスを作成する際にオプション引数commandを使って引数にbutton1_clicked関数を指定しています。
ボタンウィジェットで使えるオプション引数
ボタンウィジェットにもフレームやラベル同様、オプション引数が用意されていますがほとんど同じなので、特筆すべきもののみピックアップします。
属性 | 説明 | 値 |
---|---|---|
command | コールバック関数を指定 | 関数名 | default | ボタンの初期状態 | tk.NORMAL(通常) tk.DISABLED(押せないボタン) |
disabledforeground | ボタンが押せない時の文字色 | 色名またはカラーコード |
試しにいくつかのオプションを使って先ほどのコードに手を加えてみましょう。
# create_widget関数を定義 def create_widget(self): # label1ウィジェット self.label1 = tk.Label(self.master, text="「スイッチ」を押させるなーーーーッ", font=("MSゴシック", "20", "bold")) self.label1.pack() # button1ウィジェット self.button1 = tk.Button(self.master, text="いいや!限界だ押すね!", font=("MSゴシック", "20", "bold"), command=self.button1_clicked) # いくつかのオプション引数を設定 self.button1.pack() # button1ウィジェットを配置 def button1_clicked(self): # button1をクリックした時の処理 self.button1["text"] = "びろ~~~ん" # button1_textの中身を変更
実行結果は次のとおりです。
ラベルとボタンのフォント、フォントサイズ、文字の太さを変更し、ボタンが押された時にアプリケーションを終了するのではなく、ボタンに表示されている文字列を変更するようにしてみました。
今回文字列の変更はbutton1インスタンスのプロパティを直接変更することで実装していますが、もっと良い方法があるので後述します。
第3章 ウィジェットの配置(レイアウト)
この章ではウィジェットの配置について学びましょう。これまでは全てpackメソッドのみでウィジェットを配置してきましたが、Tkinterには他にもウィジェットを配置するためのメソッドが用意されています。
3.1 packメソッドによる1次元的な配置
まずは最も簡単なpackメソッドについてみていきましょう。
packメソッドはウィジェットを縦または横に1次元的に配列するためのメソッドで、次のオプションが用意されています。
属性 | 説明 | 値 |
---|---|---|
anchor | 配置可能なスペースに余裕がある場合、Widget をどこに配置するか指定します |
tk.CENTER(中央) tk.W(左寄せ) tk.E(右寄せ) tk.N(上寄せ) tk.S(下寄せ) tk.NW(左上) tk.SW(左下) tk.NE(右上) tk.SE(右下) |
expand | 親widget が大きくなったとき、大きくなるかどうかを指定します | 1(大きくなる) 0(サイズを保持) |
fill | widget が空いているスペースを埋めるかどうか指定します | none(元のサイズを保持) x(横に広がる) y(縦に広がる) both(縦横に広がる) |
padx | 外側の横の隙間を指定します | ピクセル単位で数値を指定 |
pady | 外側の縦の隙間を指定します | ピクセル単位で数値を指定 |
ipadx | 内側の横の隙間を指定します | ピクセル単位で数値を指定 |
ipady | 内側の縦の隙間を指定します | ピクセル単位で数値を指定 |
side | どの方向からつめていくかを指定します | top(上から) left(左から) right(右から) bottom(下から) |
例としてラベルウィジェットを3つ並べたフレームを用意しました。
#create_widget関数を定義 def create_widget(self): # ラベル1を作成 label1 = tk.Label(self.master, text="これはラベル1です", bg="lightskyblue", relief=tk.RIDGE, bd=2) label1.pack() # ラベル2を作成 label2 = tk.Label(self.master, text="ラベル2!", bg="khaki", relief=tk.RIDGE, bd=2) label2.pack() # ラベル3を作成 label3 = tk.Label(self.master, text="これはラベル3ですよおおおおおおおおおおだ", bg="yellowgreen", relief=tk.RIDGE, bd=2) label3.pack()
このコードを実行すると次のようなウィンドウが表示されます。
packメソッドではこのようにウィジェットが上から一次元的に配置されます。
試しに先ほどのコードを変更し、各ウィジェットの横幅を広げたり、各ウィジェット間に隙間を作ったりしてみましょう。次のように記述します。
# create_widget関数を定義 def create_widget(self): # ラベル1を作成 label1 = tk.Label(self.master, text="これはラベル1です", bg="lightskyblue", relief=tk.RIDGE, bd=2) label1.pack(padx=5, pady=5, fill=tk.X) # 横と縦に余白を指定し、ウィジェットを横いっぱいに広げる # ラベル2を作成 label2 = tk.Label(self.master, text="ラベル2!", bg="khaki", relief=tk.RIDGE, bd=2) label2.pack(padx=5, pady=5, fill=tk.X) # ラベル3を作成 label3 = tk.Label(self.master, text="これはラベル3ですよおおおおおおおおおおだ", bg="yellowgreen", relief=tk.RIDGE, bd=2) label3.pack(padx=5, pady=5, fill=tk.X)
各ウィジェットに縦横5ピクセルの余白を指定し、フレームの横幅いっぱいに広がるよう記述しました。
実行結果は次のとおりです。
3.2 gridメソッドによる2次元的な配置
gridメソッドはウィジェットを2次元的に配置するためのメソッドです。次のオプションが使用できます。
属性 | 説明 | 値 |
---|---|---|
column | 配置する列 | 数値 |
columnspan | 合計何列かを指定します | 数値 |
padx | 外側の横の隙間を指定します | ピクセル単位で数値を指定 |
pady | 外側の縦の隙間を指定します | ピクセル単位で数値を指定 |
ipadx | 内側の横の隙間を指定します | ピクセル単位で数値を指定 |
ipady | 内側の縦の隙間を指定します | ピクセル単位で数値を指定 |
row | 配置する行を指定します | 数値 |
rowspan | 合計何行かを指定します | 数値 |
sticky | スペースに余裕がある場合、どこに配置するか、どのように引き伸ばすかを指定します。位置決めには値を単独で、引き伸ばす場合には1つ目の値のあとで + に続けて値を指定します。 |
tk.CENTER(中央) tk.W(左寄せ) tk.E(右寄せ) tk.N(上寄せ) tk.S(下寄せ) tk.NW(左上) tk.SW(左下) tk.NE(右上) tk.SE(右下) |
実際に先ほどの3つのラベルを上段に1つ、下段に2つの2段の格子状に配置してみましょう。
次のように記述します。
#create_widget関数を定義 def create_widget(self): # ラベル1を作成 label1 = tk.Label(self, text="これはラベル1です", bg="lightskyblue", relief=tk.RIDGE, bd=2) label1.grid(row=0, column=0, columnspan=2, padx=5, pady=5) # 0行目の0列目に配置、横と縦に余白を指定 # ラベル2を作成 label2 = tk.Label(self, text="ラベル2!", bg="khaki", relief=tk.RIDGE, bd=2) label2.grid(row=1, column=0, padx=5, pady=5) # 1行目の0列目に配置、横と縦に余白を指定 # ラベル3を作成 label3 = tk.Label(self, text="これはラベル3ですよおおおおおおおおおおだ", bg="yellowgreen", relief=tk.RIDGE, bd=2) label3.grid(row=1, column=1, padx=5, pady=5) # 1行目の1列目に配置、横と縦に余白を指定
実行結果は次のとおりです。
上段、下段の2段に分かれ、2段目が2列に分かれた格子状にラベルを配置することができました。
ではまたコードを変更し、1列目のラベルを横幅いっぱいに広げてみましょう。次のように記述します。
#create_widget関数を定義 def create_widget(self): # ラベル1を作成 label1 = tk.Label(self, text="これはラベル1です", bg="lightskyblue", relief=tk.RIDGE, bd=2) label1.grid(row=0, column=0, columnspan=2, padx=5, pady=5, sticky=tk.W+tk.E) # 0行目の0列目に配置、横と縦に余白を指定、ウィジェットを横いっぱいに広げる # ラベル2を作成 label2 = tk.Label(self, text="ラベル2!", bg="khaki", relief=tk.RIDGE, bd=2) label2.grid(row=1, column=0, padx=5, pady=5) # ラベル3を作成 label3 = tk.Label(self, text="これはラベル3ですよおおおおおおおおおおだ", bg="yellowgreen", relief=tk.RIDGE, bd=2) label3.grid(row=1, column=1, padx=5, pady=5)
実行結果は次のとおりです。
1段目のラベルが横いっぱいに広がっているのがわかります。
3.3 placeメソッドによるピクセル指定での配置
placeメソッドはウィジェットをピクセル指定で直接配置する方法です。 親ウィジェットに対する相対値で指定する方法と、絶対値で指定する方法があります。
place メソッドを使うときは親フレームの width と height をあらかじめ指定しておく必要があります。次のオプションが使用できます。
属性 | 説明 | 値 |
---|---|---|
anchor | 配置可能なスペースに余裕がある場合、Widget をどこに配置するか指定します |
tk.CENTER(中央) tk.W(左寄せ) tk.E(右寄せ) tk.N(上寄せ) tk.S(下寄せ) tk.NW(左上) tk.SW(左下) tk.NE(右上) tk.SE(右下) |
bordermode | 縁を内側、外側のどちらに付けるかを指定します | tk.INSIDE(内側) tk.OUTSIDE(外側) |
width | 幅を指定します | ピクセル単位で数値を指定 |
height | 高さを指定します | ピクセル単位で数値を指定 |
relheight | 親 widget に対する相対的な高さを指定 | 0.0~1.0の実数 |
relwidth | 親 widget に対する相対的な幅を指定 | 0.0~1.0の実数 |
relx | 親 widget に対する相対的な横の位置を指定 | 0.0~1.0の実数 |
rely | 親 widget に対する相対的な縦の位置を指定 | 0.0~1.0の実数 |
x | 横の位置を指定します | ピクセル単位で数値を指定 |
y | 縦の位置を指定します | ピクセル単位で数値を指定 |
また先ほどの3つのラベルを配置してみましょう。placeメソッドであればウィジェットを斜めに配置するのも簡単です。
1つ1つの手動で設定する必要はありますが、ウィジェットを自在に配置できるのがplaceメソッドです。
第4章 ウィジェット変数
この章ではウィジェット変数ついて学びましょう。Tkinterにはウィジェットで使える変数がオブジェクトとして用意されており、これらを使うことで動的な処理を効率的に行うことができます。