見出し画像

Python入門 (6) - TkinterによるGUIの作成

「Tkinter」によるPythonのGUIの作成方法をまとめました。

前回

1. Tkinter

「Tkinter」はPythonでGUIを作成するための標準ライブラリです。

利用可能なウィジェットは、次のとおりです。

Button : ボタン
Canvas : キャンバス
Checkbutton : チェックボックス
Combobox : コンボボックス
Entry : テキストフィールド
Frame : フレーム
Label : ラベル
LabelFrame : ラベル付きフレーム
Menubutton : メニューボタン
Notebook : タブ
PanedWindow : ペインドウィンドウ
Progressbar : プログレスバー
Radiobutton : ラジオボタン
Scale : スライダーバー
Scrollbar : スクロールバー
Separator : セパレータ
Sizegrip : サイズグリップ
Treeview : ツリービュー

2. Tkinterのインストール

「Tkinter」はPythonの標準ライブラリなのでインストール不要ですが、画像を扱うのでpillowをインストールします。

$ pip install pillow

3. Hello World

画像17

「Hello World」という文字列を表示するコードは、次のとおりです。

import tkinter as tk

# アプリの定義
class HelloWorldApp(tk.Frame):
    # 初期化
    def __init__(self, master=None):
        tk.Frame.__init__(self, master, width=240, height=240)

        # タイトルの表示
        self.master.title('Hello World')
       
        # ラベルの生成
        self.label = tk.Label(self, text='Hello World')
        self.label.place(x=20, y=100, width=200, height=40)        

# アプリの実行
app= HelloWorldApp()
app.pack()
app.mainloop()

Frameのパラメータは、次のとおりです。

・bg/background : 背景色 (red,green,blue...)
・bd/bordewidth : ボーダー幅
・relief : ボーダー (tk.FLAT,tk.RAISED,tk.SUNKENN,tk.GROOVE,tk.RIDGE)
・width : 幅 (px)
・height : 高さ (px)

4. ウィジェットの配置

ウィジェットの配置方法には、絶対座標配置、一列配置、グリッド配置の3種類があります。

ウィジェットの絶対座標配置

画像15

ウィジェットの絶対座標配置のコードは、次のとおりです。

import tkinter as tk

# アプリの定義
class PlaceApp(tk.Frame):
    # 初期化
    def __init__(self, master=None):
        tk.Frame.__init__(self, master, width=240, height=240)

        # タイトルの表示
        self.master.title('ウィジェットの絶対座標配置')
       
        # ラベル1の生成
        label1 = tk.Label(self, text='ラベル1◎◎◎◎', bg='LightSkyBlue')
        label1.place(x=10, y=10)
    
        # ラベル2の生成
        label2 = tk.Label(self, text='ラベル2◎◎', bg='LightSkyBlue')
        label2.place(x=120, y=10)
  
        # ラベル3の生成
        label3 = tk.Label(self, text='ラベル3◎◎◎', bg='LightSkyBlue')
        label3.place(x=10, y=50)        

# アプリの実行
app= PlaceApp()
app.pack()
app.mainloop()

place()のパラメータは、次のとおりです。

・anchor : アンカー (tk.CENTER,tk.W,tk.E,tk.N,tk.S または"news"の組み合わせ)
・bordermode : ボーダーモード (tk.INSIDE,tk.OUTSIDE)
・x : X座標(px)
・y : Y座標(px)
・width : 幅(px)
・height : 高さ(px)
・relx : 親ウィジェットに対する相対X座標 (0.0〜1.0)
・rely : 親ウィジェットに対する相対Y座標 (0.0〜1.0)
・relwidth : 親ウィジェットに対する相対幅 (0.0〜1.0)
・relheight : 親ウィジェットに対する相対高さ (0.0〜1.0)

◎ ウィジェットの一列配置
ウィジェットの一列配置のコードは、次のとおりです。

画像27

ウィジェットの一列配置のコードは、次のとおりです。

import tkinter as tk

# アプリの定義
class PackApp(tk.Frame):
    # 初期化
    def __init__(self, master=None):
        tk.Frame.__init__(self, master)
      
        # タイトルとウィンドウサイズの指定
        self.master.title('ウィジェットの一列配置')
        self.master.geometry('240x240')     

        # ラベル1の生成
        label1 = tk.Label(self, text='ラベル1', bg='red')
        label1.pack(padx=5, pady=5)
   
        # ラベル2の生成
        label2 = tk.Label(self, text='ラベル2', bg='green')
        label2.pack(padx=5, pady=5)
 
        # ラベル3の生成
        label3 = tk.Label(self, text='ラベル3', bg='blue')
        label3.pack(padx=5, pady=5)        

# アプリの実行
app= PackApp()
app.pack(anchor='nw', expand=True)
app.mainloop()

pack()のパラメータは、次のとおりです。

・anchor : アンカー (tk.CENTER,tk.W,tk.E,tk.N,tk.S または"news"の組み合わせ)
・expand : 親ウィジェットのサイズ変更時に影響されるか (0 or 1)
・fill : ウィジェットの空きスペースを埋めるかどうか (tk.NONE,tk.X,tk.Y,tk.BOTH)
・padx : 外側の横のスペース (px)
・pady : 外側の縦のスペース (px)
・ipadx : 内側の横のスペース (px)
・ipady : 内側の縦のスペース (px)
・side : 列の方向 (tk.TOP,tk.LEFT,tk.RIGHT,tk.BOTTOM)

◎ ウィジェットのグリッド配置

画像27

ウィジェットのグリッド配置のコードは、次のとおりです。

import tkinter as tk

# アプリの定義
class GridApp(tk.Frame):
    # 初期化
    def __init__(self, master=None):
        tk.Frame.__init__(self, master)

        # タイトルとウィンドウサイズの指定
        self.master.title('ウィジェットのグリッド配置')
        self.master.geometry('240x240')

        # 伸縮の指定
        self.master.columnconfigure(0, weight=1)
        self.master.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        # ラベル1の生成
        label1 = tk.Label(self, text='ラベル1', bg='red', height=100)
        label1.grid(row=0, column=0, columnspan=2, sticky='news', padx=5, pady=5)
   
        # ラベル2の生成
        label2 = tk.Label(self, text='ラベル2', bg='green')
        label2.grid(row=1, column=0, sticky='news', padx=5, pady=5)
 
        # ラベル3の生成
        label3 = tk.Label(self, text='ラベル3', bg='blue')
        label3.grid(row=1, column=1, sticky='news', padx=5, pady=5)   

# アプリの実行
app= GridApp()
app.grid(sticky='news') # 伸縮の指定
app.mainloop()

grid()のパラメータは、次のとおりです。

・row : 配置する行位置
・rowspan : 配置する行数
・column : 配置する列位置
・columnspan : 配置する列数
・padx : 外側の横のスペース (px)
・pady : 外側の縦のスペース (px)
・ipadx : 内側の横のスペース (px)
・ipady : 内側の縦のスペース (px)
・sticky : anchor + fill (tk.CENTER,tk.W,tk.E,tk.N,tk.S または"news"の組み合わせ)

5. キャンバス

◎ グラフィックスの描画

画像2

グラフィックスの描画を行うコードは、次のとおりです。

import tkinter as tk

# アプリの定義
class GraphicsApp(tk.Frame):
    # 初期化
    def __init__(self, master=None):
        tk.Frame.__init__(self, master, width=240, height=240)

        # タイトルの表示
        self.master.title('グラフィックの描画')
       
        # キャンバスの生成
        self.c = tk.Canvas(self, highlightthickness=0)
        self.c.place(x=0, y=0, width=240, height=240)

        # 描画の更新
        self.on_draw()       
      
    # 描画の更新
    def on_draw(self):
        # 描画のクリア
        self.c.delete('all')

        # ラインの描画
        self.c.create_line(10, 30, 230, 30, width=2.0, fill='#FF0000')

        # 円の描画
        self.c.create_oval(10, 70, 50, 110, width=2.0, outline='#00FF00')

        # 円の塗り潰し
        self.c.create_oval(70, 70, 110, 110, width=0.0, fill='#00FF00')

        # 矩形の描画
        self.c.create_rectangle(10, 130, 50, 170, width=2.0, outline='#00A0FF')

        # 矩形の塗り潰し
        self.c.create_rectangle(70, 130, 110, 170, width=0.0, fill='#00A0FF')

        # 文字列の表示
        self.c.create_text(10, 200, text='Hello World', font='courier 20', anchor=tk.NW)        

# アプリの実行
app = GraphicsApp()
app.pack()
app.mainloop()

◎ イメージの描画

画像3

sample.png

画像4

イメージの描画を行うコードは、次のとおりです。

import tkinter as tk
from PIL import Image, ImageTk

# アプリの定義
class ImageApp(tk.Frame):
    # 初期化
    def __init__(self, master=None):
        tk.Frame.__init__(self, master, width=240, height=240)

        # タイトルの表示
        self.master.title('イメージの描画')

        # イメージの読み込み
        image = Image.open('sample.png')
        self.images = []
        self.images.append(ImageTk.PhotoImage(image))
        self.images.append(ImageTk.PhotoImage(image.rotate(180)))

        # キャンバスの生成
        self.c = tk.Canvas(self, highlightthickness=0)
        self.c.place(x=0, y=0, width=240, height=240)

        # 描画の更新
        self.on_draw()           

    # 描画の更新
    def on_draw(self):
        # 描画のクリア
        self.c.delete('all')

        # イメージの描画
        self.c.create_image(10, 10, image=self.images[0],  anchor=tk.NW)

        # 反転イメージの描画
        self.c.create_image(10, 100, image=self.images[1],  anchor=tk.NW)

# アプリの実行
f = ImageApp()
f.pack()
f.mainloop()

◎ マウスイベント

画像7

マウスでクリックした位置を表示するコードは、次のとおりです。

import tkinter as tk
from PIL import Image, ImageTk

# アプリの定義
class MouseApp(tk.Frame):
    # 初期化
    def __init__(self, master=None):
        tk.Frame.__init__(self, master, width=240, height=240)

        # タイトルの表示
        self.master.title('マウスイベント')

        # クリック位置
        self.x = 0
        self.y = 0

        # キャンバスの生成
        self.c = tk.Canvas(self, width = 240, height = 240, highlightthickness = 0)
        self.c.bind('<Button-1>', self.on_click) # クリック判定の追加
        self.c.pack()

        # 描画の更新
        self.on_draw() 
                 
    # クリック時に呼ばれる
    def on_click(self, event):
        self.x = event.x
        self.y = event.y
        self.on_draw()

    # 描画の更新
    def on_draw(self):
        # 描画のクリア
        self.c.delete('all')

        # 文字列の表示
        str = 'クリック位置 {},{}'.format(self.x, self.y)
        self.c.create_text(10, 10, text = str, font='courier 16', anchor=tk.NW)

# アプリの実行
f = MouseApp()
f.pack()
f.mainloop()

6. ラベル

◎ 文字列

画像8

ラベルを利用するコードは、次のとおりです。

import tkinter as tk
from PIL import Image, ImageTk

# アプリの定義
class MouseApp(tk.Frame):
    # 初期化
    def __init__(self, master=None):
        tk.Frame.__init__(self, master, width=240, height=240)

        # タイトルの表示
        self.master.title('ラベル')

        # ラベルの生成
        self.label = tk.Label(self, text='Hello World',
            font=('', 20),
            foreground='#ffffff',
            background='#0000aa')
        self.label.place(x=20, y=100, width=200, height=40)
                 
# アプリの実行
f = MouseApp()
f.pack()
f.mainloop()

◎ イメージ

画像13

画像14

ラベルをイメージビューとして利用するコードは、次のとおりです。

import tkinter as tk

# アプリの定義
class ImageLabelApp(tk.Frame):
    # 初期化
    def __init__(self, master=None):
        tk.Frame.__init__(self, master, width=240, height=240)
 
        # タイトルの表示
        self.master.title('イメージビュー')

        # イメージビューの生成
        self.photo = tk.PhotoImage(file='sample.png') # メモリ回収防止のためインスタンス変数で保持
        self.label = tk.Label(self, image=self.photo)
        self.label.place(x=80, y=80, width=80, height=80)
                 
# アプリの実行
f = ImageLabelApp()
f.pack()
f.mainloop()

7. ボタン

画像6

画像7

ボタンを利用するコードは、次のとおりです。

import tkinter as tk
from tkinter import messagebox

# アプリの定義
class ButtonApp(tk.Frame):
    # 初期化
    def __init__(self, master=None):
        tk.Frame.__init__(self, master, width=240, height=240)

        # タイトルの表示
        self.master.title('ボタン')

        # ボタンの生成
        self.button = tk.Button(self, text='OK', command=self.on_click) 
        self.button.place(x=20, y=100, width=200, height=40)
       
    # クリック時に呼ばれる
    def on_click(self):
        messagebox.showinfo('情報', 'ボタンをクリックしました')        

# アプリの実行
app = ButtonApp()
app.pack()
app.mainloop()

メッセージボックスの種類は、次のとおりです。

・messagebox.showinfo() : 情報
・messagebox.showwarning() : 警告
・messagebox.showerror() : エラー
・messagebox.askquestion() : 質問
・messagebox.askokcancel() : OK・キャンセル
・messagebox.askyesno() : YES・NO
・messagebox.askretrycansel() : リトライ・キャンセル

8. テキストフィールド

◎ 単一行のテキストフィールド

画像18

画像10

単一行のテキストフィールドを利用するコードは、次のとおりです。

import tkinter as tk
from tkinter import messagebox

# アプリの定義
class TextFieldApp(tk.Frame):
    # 初期化
    def __init__(self, master=None):
        tk.Frame.__init__(self, master, width=240, height=240)

        # タイトルの表示
        self.master.title('単一行のテキストフィールド')
      
        # 単一行のテキストフィールドの生成
        self.text_field = tk.Entry()
        self.text_field.place(x=10, y=100, width=170, height=40)
      
        # ボタンの生成
        self.button = tk.Button(self, text='OK', command=self.on_click) 
        self.button.place(x=180, y=100, width=50, height=40)
      
    # クリック時に呼ばれる
    def on_click(self):
        messagebox.showinfo('情報', self.text_field.get()+'を入力しました')        

# アプリの実行
app = TextFieldApp()
app.pack()
app.mainloop()

◎ 複数行のテキストフィールド

画像19

画像20

複数行のテキストフィールドを利用するコードは、次のとおりです。

import tkinter as tk
from tkinter import messagebox

# アプリの定義
class MultiTextFieldApp(tk.Frame):
    # 初期化
    def __init__(self, master=None):
        tk.Frame.__init__(self, master, width=240, height=240)

        # タイトルの表示
        self.master.title('複数行のテキストフィールド')
      
        # 複数行のテキストフィールドの生成
        self.text_field = tk.Text()
        self.text_field.place(x=10, y=90, width=170, height=60)
      
        # ボタンの生成
        self.button = tk.Button(self, text='OK', command=self.on_click) 
        self.button.place(x=180, y=100, width=50, height=40)
      
   # クリック時に呼ばれる
   def on_click(self):
       messagebox.showinfo('情報', self.text_field.get('1.0', 'end -1c')+'を入力しました')        

# アプリの実行
app = MultiTextFieldApp()
app.pack()
app.mainloop()

Textの操作方法は、次のとおりです。

・テキストの挿入 : text_field.insert('1.0', text)
・テキストの取得 : text = text_field.get('1.0', 'end -1c')
・テキストの削除 : text_field.delete('1.0', 'end')
・テキストの編集無効 : text_field.configure(state='disabled')

◎ スクロール可能なテキストフィールド

画像21

スクロール可能なテキストフィールドを利用するコードは、次のとおりです。

import tkinter as tk
from tkinter.scrolledtext import ScrolledText

# アプリの定義
class ScrollTextFieldApp(tk.Frame):
    # 初期化
    def __init__(self, master=None):
        tk.Frame.__init__(self, master, width=240, height=240)

        # タイトルの表示
        self.master.title('スクロール可能なテキストフィールド')
       
        # テキストの生成
        text = ''
        for i in range(100):
            text += 'あいうえおかきくけこさしすせそたちつてとなにぬねの'
       
        # スクロール可能なテキストフィールドの生成
        text_field = ScrolledText(self)
        text_field.insert(1.0, text)
        text_field.configure(state='disabled') # 編集無効        
        text_field.place(x=0, y=0, width=240, height=240)

# アプリの実行
app = ScrollTextFieldApp()
app.pack()
app.mainloop()

9. リストボックス

画像16

画像17

リストボックスを利用するコードは、次のとおりです。

import tkinter as tk
from tkinter import messagebox

# アプリの定義
class ListBoxApp(tk.Frame):
    # 初期化
    def __init__(self, master=None):
        tk.Frame.__init__(self, master, width=240, height=240)

        # タイトルの表示
        self.master.title('リストボックス')
       
        # リストボックス
        items = ['アイテム1', 'アイテム2', 'アイテム3', 'アイテム4', 'アイテム5', 'アイテム6']
        self.list_box = tk.Listbox(self, listvariable=tk.StringVar(value=items), selectmode='browse')
        self.list_box.bind('<<ListboxSelect>>', lambda e: self.on_select())
        self.list_box.place(x=10, y=10, width=220, height=220)
       
    # 選択時に呼ばれる
    def on_select(self):
        for i in self.list_box.curselection():
            messagebox.showinfo('情報', self.list_box.get(i)+'を選択しました')   

# アプリの実行
app = ListBoxApp()
app.pack()
app.mainloop()

10. メニュー

画像21

メニューを利用するコードは、次のとおりです。

import tkinter as tk
from tkinter import messagebox

# アプリの定義
class MenuApp(tk.Frame):
    # 初期化
    def __init__(self, master=None):
        tk.Frame.__init__(self, master, width=240, height=240)

        # タイトルの表示
        self.master.title('メニュー')
      
        # メニューの生成
        menu = tk.Menu(self)
       
        # ファイルメニューの追加
        file_menu = tk.Menu(menu, tearoff=0)
        file_menu.add_command(label='ファイルを開く', command=self.on_file_open)
        file_menu.add_command(label='ファイルを保存', command=self.on_file_save)
        file_menu.add_separator()
        file_menu.add_command(label='終了', command=quit)
        menu.add_cascade(label='ファイル', menu=file_menu)
       
        # ヘルプメニューの追加
        help_menu = tk.Menu(menu, tearoff=0)
        help_menu.add_command(label='ヘルプ', command=self.on_help)
        menu.add_cascade(label='ヘルプ', menu=help_menu)
       
        # メニューの指定
        self.master.config(menu=menu)
       
    # ファイルを開く
    def on_file_open(self):
        messagebox.showinfo('情報', 'ファイルを開くをクリックしました')

    # ファイルを保存
    def on_file_save(self):
        messagebox.showinfo('情報', 'ファイルを保存をクリックしました')
      
    # ヘルプ 
    def on_help(self):
        messagebox.showinfo('情報', 'ヘルプをクリックしました')   

# アプリの実行
app = MenuApp()
app.pack()
app.mainloop()

12. コンボボックス

画像22

画像23

コンボボックスを利用するコードは、次のとおりです。

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox

# アプリの定義
class ComboboxdApp(tk.Frame):
    # 初期化
    def __init__(self, master=None):
        tk.Frame.__init__(self, master, width=240, height=240)

        # タイトルの表示
        self.master.title('コンボボックス')
       
        # コンボボックスの生成
        items = ['アイテム1', 'アイテム2', 'アイテム3', 'アイテム4', 'アイテム5']
        self.combobox = ttk.Combobox(self, textvariable=tk.StringVar(), 
            values=items, width=10)
        self.combobox.set(items[0])
        self.combobox.place(x=10, y=100, width=170, height=40)
       
        # ボタンの生成
        self.button = tk.Button(self, text='OK', command=self.on_click) 
        self.button.place(x=180, y=100, width=50, height=40)
     
    # クリック時に呼ばれる
    def on_click(self):
        messagebox.showinfo('情報', self.combobox.get()+'を入力しました')         

# アプリの実行
app= ComboboxdApp()
app.pack()
app.mainloop()

13. チェックボックス

画像24

画像25

チェックボックスを利用するコードは、次のとおりです。

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox

# アプリの定義
class CheckboxdApp(tk.Frame):
    # 初期化
    def __init__(self, master=None):
        tk.Frame.__init__(self, master, width=240, height=240)

        # タイトルの表示
        self.master.title('チェックボックス')
       
        # チェックボックス1の生成
        self.value1 = tk.BooleanVar()
        self.value1.set(True)
        self.checkbox1 = ttk.Checkbutton(self, 
            variable=self.value1, text='チェックボックス1')
        self.checkbox1.place(x=10, y=80, width=170, height=40)
       
        # チェックボックス2の生成
        self.value2 = tk.BooleanVar()
        self.value2.set(False)
        self.checkbox2 = ttk.Checkbutton(self, 
            variable=self.value2, text='チェックボックス2')
        self.checkbox2.place(x=10, y=120, width=170, height=40)

        # ボタンの生成
        self.button = tk.Button(self, text='OK', command=self.on_click) 
        self.button.place(x=180, y=100, width=50, height=40)
     
    # クリック時に呼ばれる
    def on_click(self):
        messagebox.showinfo('情報', 
            str(self.value1.get())+'と'+str(self.value2.get())+'を入力しました')         

# アプリの実行
app= CheckboxdApp()
app.pack()
app.mainloop()

14. ラジオボタン

画像26

画像27

ラジオボタンを利用するコードは、次のとおりです。

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox

# アプリの定義
class RadioButtonApp(tk.Frame):
    # 初期化
    def __init__(self, master=None):
        tk.Frame.__init__(self, master, width=240, height=240)

        # タイトルの表示
        self.master.title('ラジオボタン')
       
        # ラジオボタンの値
        self.value = tk.StringVar()
        self.value.set('1')
       
        # ラジオボタン1の生成
        self.radiobutton1 = ttk.Radiobutton(self, 
            variable=self.value, value='1', text='ラジオボタン1')
        self.radiobutton1.place(x=10, y=80, width=170, height=40)
       
        # ラジオボタン2の生成
        self.radiobutton2 = ttk.Radiobutton(self, 
            variable=self.value, value='2', text='ラジオボタン2')
        self.radiobutton2.place(x=10, y=120, width=170, height=40)

        # ボタンの生成
        self.button = tk.Button(self, text='OK', command=self.on_click) 
        self.button.place(x=180, y=100, width=50, height=40)
     
    # クリック時に呼ばれる
    def on_click(self):
        messagebox.showinfo('情報', 
            str(self.value.get())+'を入力しました')         

# アプリの実行
app= RadioButtonApp()
app.pack()
app.mainloop()

次回



この記事が気に入ったらサポートをしてみませんか?