
Python CustomTkinterを使ったGUI画面作成の備忘録(基本操作編)
はじめに
CanSatの地上局作成の一部に,PythonのCunstomTkinterを使ったGUI操作画面を採用することになったので備忘録として残そうと思います.今回は基本操作編です.
CustomTkinterとは
CustomTkinterとは,Python標準のGUIライブラリtkinterを拡張したライブラリです.tkinterとの違いとして,ダークモードなどのより現代的なデザインが使用できます.

環境構築
pipコマンドでCustomTkinterをインストールします.
pip install customtkinter
基本的なプログラムの作成
まずは以下のコードを実行してみてください.
import customtkinter as ctk
# customtkinterのテーマを設定
ctk.set_appearance_mode("System") # "Light"や"Dark"も選べる
ctk.set_default_color_theme("blue") # "green"や"dark-blue"も選べる
# アプリの基本設定
app = ctk.CTk() # customtkinterを使ったウィンドウ作成
app.title("CustomTkinter 練習アプリ")
app.geometry("400x300") # ウィンドウサイズ
# テキストラベル
label = ctk.CTkLabel(app, text="ボタンを押してみてください。", font=("Arial", 16))
label.pack(pady=20)
# ボタンを押したときの動作
def on_button_click():
label.configure(text="ボタンが押されました!")
# ボタンを作成
button = ctk.CTkButton(app, text="クリック", command=on_button_click)
button.pack(pady=20)
# アプリを実行
app.mainloop()
するとこのような画面が表示されると思うので,「ボタンを押してみてください」というボタンを押してください.すると新たな表示に変更されると思います.

コードの詳細を説明します.
必要ライブラリのインポート
必要なライブラリをインポートします.
import customtkinter as ctk
ここでは,CustomTkinterを使うために"customtkinter"ライブラリをインポートしています.さらに,"as ctk"を使うことで,"customtkinter"を"ctk"と短縮して表記でき,コードがより簡潔になります.
テーマの設定
アプリ全体の外見の設定と,アプリ内のウィジェットの設定を行います.
# customtkinterのテーマを設定
ctk.set_appearance_mode("System") # "Light"や"Dark"も選べる
ctk.set_default_color_theme("blue") # "green"や"dark-blue"も選べる
1.アプリ全体の外見の設定 ctk.set_appearance_mode("System")
ウインドウ全体の背景色を設定します.設定が影響する部分は,背景色,テキスト色などです.

2.アプリ内のウィジェットの色設定
ウィジェットの色設定を行います.設定が影響する部分は,ボタンやスライダー,プログレスバーなどです.

アプリの基本設定
# アプリの基本設定
app = ctk.CTk() # customtkinterを使ったウィンドウ作成
app.title("CustomTkinter 練習アプリ")
app.geometry("400x300") # ウィンドウサイズ
1.メインウィンドウの作成
メインウィンドウ(トップレベルウィンドウ)を作成します.CustomTkinterでは,CTkがメインウィンドウを作成するクラスであり,ここではメインウィンドウはappとして定義しています.
2.メインウィンドウのウィンドウ名の設定(app.title("任意の名前を入れる")
ウィンドウのタイトルバーに表示されるウィンドウ名を設定します.

3.ウィンドウのサイズの設定 app.geometry("400x300")
ウィンドウのサイズ(横と縦)をピクセル単位で設定します.
テキストラベルの設定
# テキストラベル
label = ctk.CTkLabel(app, text="ボタンを押してみてください。", font=("Arial", 16))
label.pack(pady=20)
1.テキストラベルの作成 label=ctk.CTKLabel(…)
ウィンドウ内にテキストラベルを作成するコードです.各パラメータの説明は以下の通りです.
1.1.app
CTKLabelをどのウインドウに配置するか指定します.この場合,メインウィンドウであるappに配置しています.
1.2.text="ボタンを押してみてください。"
ラベルに表示する文字列を指定しています.
1.3.font=("Arial",16)
フォントの種類(Arial)とフォントサイズ(16)を指定しています.なお,フォント設定を省略すると以下のデフォルト設定が反映されます.
font=("Helvetica", 20, "bold") # 20ポイントの太字Helveticaフォント
まとめると,以下のようになります.
label = ctk.CTkLabel(配置するウインドウの指定, text="ラベルの内容", フォント設定)
2.テキストラベルの配置 label.pack(pady=20)
作成したテキストラベルをウインドウのどの位置に配置するか指定します.例ではpadyを使って上下方向に20ピクセルの余白を追加しています.他には以下のような設定できます.
label.pack(pady=20) # 上下方向20ピクセルの余白を追加
#top:上揃え(デフォルト)
#bottom:下揃え
#left:左揃え
#right:右揃え
ボタンを押したときの動作
ボタンを押したときの動作を設定します.
# ボタンを押したときの動作
def on_button_click():
label.configure(text="ボタンが押されました!")
1.関数の定義
def関数を使ってon_button_click()関数を定義しています.
1.1.configure()を用いて表示されるテキストを変更
configure()を使って表示されるテキストを変更しています.configureメソッドは「既存のウィジェットの設定を変更するメソッド」です.
ボタンの作成
ボタンを作成します.
# ボタンを作成
button = ctk.CTkButton(app, text="クリック", command=on_button_click)
button.pack(pady=20)
1.ボタンの作成
ctk.CTkButtonを使ってボタンの作成します.
1.1.app
ボタンを配置する箇所を指定しています.今回はメインウィンドウです.
1.2.text="クリック"
ボタンに表示させる文字列です.
1.3.command=on_button_click
ボタンが押されたときに実行される動作を指定します.command引数には関数を渡します.ここでは,さきほど定義したon_button_click関数を指定しています.
2.ボタンの配置
テキストラベルの配置と同様に設定します.
イベントループの開始(アプリケーションの実行)
# アプリを実行
app.mainloop()
mainloop()を使ってアプリケーションが終了するまでウインドウを表示し続けます.
サブウインドウの作成
ボタンを押されたらサブウインドウに移動する例です.
import customtkinter as ctk
# アプリ設定
app = ctk.CTk()
app.geometry("400x200")
app.title("メインウィンドウ")
# 別のウィンドウを作成する関数
def open_new_window():
# サブウィンドウを作成
new_window = ctk.CTkToplevel(app)
new_window.geometry("400x200")
new_window.title("サブウィンドウ")
# サブウィンドウにウィジェットを追加
label = ctk.CTkLabel(new_window, text="これはサブウィンドウです", font=("Arial", 16))
label.pack(pady=70)
# メインウィンドウのボタン
main_button = ctk.CTkButton(app, text="新しいウィンドウを開く", command=open_new_window)
main_button.pack(pady=70)
# アプリ実行
app.mainloop()
"def open_new_window():"でサブウインドウを作成しています.
ウインドウの階層構造
CustomTkinterのウインドウは以下のような階層構造となっており,Toplevelでサブウインドウの作成が可能です.また,Toplevelクラスを使って作成されたサブウインドウは独立したウインドウとして機能します.各Toplevelインスタンスはそれぞれ別々のメモリ領域で管理されており,複数作成しても競合することはありません(多分… この辺りの認識甘いのでご指摘していただけると助かります)

以下は2つのサブウインドウを表示させる例です.
import customtkinter as ctk
# アプリ設定
app = ctk.CTk()
app.geometry("400x300")
app.title("メインウィンドウ")
# サブウィンドウ1を作成する関数
def open_window1():
window1 = ctk.CTkToplevel(app)
window1.geometry("300x200")
window1.title("サブウィンドウ1")
label1 = ctk.CTkLabel(window1, text="これはサブウィンドウ1です")
label1.pack(pady=20)
button1 = ctk.CTkButton(window1, text="閉じる", command=window1.destroy)
button1.pack(pady=10)
# サブウィンドウ2を作成する関数
def open_window2():
window2 = ctk.CTkToplevel(app)
window2.geometry("300x200")
window2.title("サブウィンドウ2")
label2 = ctk.CTkLabel(window2, text="これはサブウィンドウ2です")
label2.pack(pady=20)
button2 = ctk.CTkButton(window2, text="閉じる", command=window2.destroy)
button2.pack(pady=10)
# メインウィンドウのボタン
button_window1 = ctk.CTkButton(app, text="サブウィンドウ1を開く", command=open_window1)
button_window1.pack(pady=40)
button_window2 = ctk.CTkButton(app, text="サブウィンドウ2を開く", command=open_window2)
button_window2.pack(pady=40)
# アプリ実行
app.mainloop()

入力フィールドの作成
ユーザーが文字を入力できるテキストボックスの作成例です.
import customtkinter as ctk
# アプリ設定
app = ctk.CTk()
app.geometry("400x200")
app.title("CTkEntryの例")
# 入力フィールドの作成
entry = ctk.CTkEntry(app, placeholder_text="ここに入力してください")
entry.pack(pady=20)
# 入力内容を取得して表示する関数
def show_input():
user_input = entry.get() # ユーザーが入力した内容を取得
print(f"入力内容: {user_input}")
# ボタンを作成して入力内容を表示
button = ctk.CTkButton(app, text="入力を表示", command=show_input)
button.pack(pady=10)
# アプリを実行
app.mainloop()
入力フィールド作成箇所の説明です.
# 入力フィールドの作成
entry = ctk.CTkEntry(app, placeholder_text="ここに入力してください")
entry.pack(pady=20)
1.入力フィールドの作成
CTk.Entryを使って入力フィールドを作成しています.
1.1.app
入力フィールドを配置するウインドウをappとして指定します.
1.2.placeholder_text="ここに入力してください
入力フィールドに表示されるヒントテキストを設定します.ユーザーが何も入力していないときに表示される薄い文字列です.
2.入力内容を取得する関数の作成 show_input()
2.1.入力内容の取得 user_input = entry.get()
entry.get()を使って,先ほど定義した入力フィールド"entry"に入力され ている文字列を取得しています.この動作を行うentry.get()をuser_inputとして定義しています.
2.2 コンソール(ターミナル)に出力 print(f"…")
入力フィールドから取得した文字列をコンソールに出力します.今回は2.1で定義した入力フィールドから取得した文字列user_inputを出力しています.

スイッチ(CTkSwitch)の作成
スイッチの作成例です.
import customtkinter as ctk
# アプリ設定
app = ctk.CTk()
app.geometry("400x200")
app.title("CTkSwitch の例")
# スイッチの作成
switch = ctk.CTkSwitch(app, text="スイッチ")
switch.pack(pady=20)
# スイッチの状態を取得して表示する関数
def show_switch_state():
state = "ON" if switch.get() else "OFF" # スイッチの状態を取得
print(f"スイッチの状態: {state}")
# 状態を表示するボタン
button = ctk.CTkButton(app, text="状態確認", command=show_switch_state)
button.pack(pady=10)
# アプリ実行
app.mainloop()
スイッチを作成している箇所に関する説明です.
1.スイッチの作成
# スイッチの作成
switch = ctk.CTkSwitch(app, text="スイッチ")
switch.pack(pady=20)
1.1.CTkSwitchクラスを使ったスイッチの作成
CTk.Switchクラスを使ってスイッチを作成します.また,appでスイッチをメインウィンドウに,textを使ってスイッチの横に文字列を表示させます.
1.2.スイッチの配置
ウインドウ内に作成したスイッチを"switch.pack(pady=20)"で配置します.
2.スイッチの状態に応じた動作の設定
スイッチの状態を取得して表示させる関数"show_switch_state()"を作成します.
# スイッチの状態を取得して表示する関数
def show_switch_state():
state = "ON" if switch.get() else "OFF" # スイッチの状態を取得
print(f"スイッチの状態: {state}")
2.1 state = "ON" if switch.get() else "OFF"
スイッチの状態を取得します.以下のように設定すると,スイッチがONのときは"ON",スイッチがOFFのときは"OFF"となります.

2.2. print(f"スイッチの状態: {state}")
取得した状態"state"をコンソールに出力します.

チェックボックスの作成
チェックボックスの作成例です.
import customtkinter as ctk
# アプリ設定
app = ctk.CTk()
app.geometry("400x200")
app.title("CTkCheckBoxの例")
# チェックボックスを作成
checkbox = ctk.CTkCheckBox(app, text="チェックボックス")
checkbox.pack(pady=20)
# チェックボックスの状態を取得して表示する関数
def show_checkbox_state():
state = "選択済み" if checkbox.get() else "未選択"
print(f"チェックボックスの状態: {state}")
# 状態を確認するボタン
button = ctk.CTkButton(app, text="状態確認", command=show_checkbox_state)
button.pack(pady=10)
# アプリ実行
app.mainloop()
チェックボックスに関する箇所の説明です.
1.チェックボックスの作成と配置
# チェックボックスを作成
checkbox = ctk.CTkCheckBox(app, text="チェックボックス")
checkbox.pack(pady=20)
1.1.チェックボックスの作成
CTkCheckBoxクラスを用いてチェックボックスを作成します.appでチェックボックスをメインウィンドウに,textを使ってチェックボックス横に文字列を表示させます.
1.2.チェックボックスの配置
ウインドウ内に作成したチェックボックスを"checkbox.pack(pady=20)"で配置します.
2.チェックボックスの状態に応じた動作の設定
チェックボックスの状態を取得する関数"show_checkbox_state()"を作成します.
# チェックボックスの状態を取得して表示する関数
def show_checkbox_state():
state = "選択済み" if checkbox.get() else "未選択"
print(f"チェックボックスの状態: {state}")
2.1.state = "選択済み" if checkbox.get() else "未選択"
チェックボックスの状態を取得します.以下のように設定すると,チェックボックがONのときは"選択済み",チェックボックがOFFのときは"未選択"という状態を出力します.

2.2 print(f"チェックボックスの状態: {state}")
取得した状態"state"をコンソールに出力します.

スライダーの作成
スライダーの作成例です.
import customtkinter as ctk
# アプリ設定
app = ctk.CTk()
app.geometry("400x200")
app.title("CTkSlider の例")
# スライダーの作成
slider = ctk.CTkSlider(app, from_=0, to=100)
slider.pack(pady=20)
# スライダーの値を取得して表示する関数
def show_slider_value():
value = slider.get()
print(f"スライダーの値: {value}")
# ボタンを作成して値を確認
button = ctk.CTkButton(app, text="値を表示", command=show_slider_value)
button.pack(pady=10)
# アプリ実行
app.mainloop()
スライダーの箇所の説明です.
1.スライダーの作成
# スライダーの作成
slider = ctk.CTkSlider(app, from_=0, to=100)
slider.pack(pady=20)
1.1.スライダーの作成
CTkSliderクラスを用いてスライダーを作成します.appでスライダーをメインウィンドウに,fromとtoを用いてスライダーの最小値と最大値を設定します.
1.2.スライダーの配置
ウインドウ内に作成したスライダーを"slider.pack(pady=20)"で配置します.
2.スライダーの状態に応じた動作の設定
スライダーの状態を取得する関数"show_slider_value()"を作成します.
# スライダーの値を取得して表示する関数
def show_slider_value():
value = slider.get()
print(f"スライダーの値: {value}")
2.1.value = slider.get()
slider.get()を使ってスライダーの値を取得してvalueとします.
2.2.print(f"スライダーの値: {value}")
取得した値"value"をコンソールに出力します.

ドロップダウンメニューの作成
ドロップダウンメニューの作成例です.
import customtkinter as ctk
# アプリ設定
app = ctk.CTk()
app.geometry("400x200")
app.title("CTkComboBox の例")
# ドロップダウンメニューの作成
combobox = ctk.CTkComboBox(app, values=["選択肢1", "選択肢2", "選択肢3"])
combobox.pack(pady=20)
# ドロップダウンメニューの選択値を取得して表示する関数
def show_selected_value():
value = combobox.get()
print(f"選択された値: {value}")
# ボタンを作成して選択値を表示
button = ctk.CTkButton(app, text="選択値を表示", command=show_selected_value)
button.pack(pady=10)
# アプリ実行
app.mainloop()
ドロップダウンメニューを作成している箇所に関する説明です.
1.ドロップダウンメニューの作成
# ドロップダウンメニューの作成
combobox = ctk.CTkComboBox(app, values=["選択肢1", "選択肢2", "選択肢3"])
combobox.pack(pady=20)
1.1.CTkComboBoxクラスを使ったドロップダウンメニューの作成
CTkComboBoxクラスを使ってドロップダウンメニューを作成します.appでスイッチをメインウィンドウに設定します.また,ドロップダウンに表示される選択肢(今回は"選択肢1","選択肢2","選択肢3)をvaluesに設定します.
1.2.ドロップダウンメニューの配置
ウインドウ内に作成したドロップダウンメニューを"combobox.pack(pady=20)"で配置します.
2.ドロップダウンメニューの状態に応じた動作の設定
ドロップダウンメニューの状態を取得する関数"show_selected_value()"を作成します.
# ドロップダウンメニューの選択値を取得して表示する関数
def show_selected_value():
value = combobox.get()
print(f"選択された値: {value}")
2.1. value = combobox.get()
combobox.get()を使ってドロップダウンメニューの値を取得してvalueとします.
2.2.print(f"選択された値: {value}")
取得した値"value"をコンソールに出力します.

ラジオボタンの作成
ラジオボタンの作成例です.
import customtkinter as ctk
# アプリ設定
app = ctk.CTk()
app.geometry("300x200")
app.title("CTkRadioButton の例")
# 選択値を保持する変数
selected_option = ctk.StringVar(value="オプション1")
# ラジオボタンを作成
radio1 = ctk.CTkRadioButton(app, text="オプション1", variable=selected_option, value="オプション1")
radio1.pack(pady=5)
radio2 = ctk.CTkRadioButton(app, text="オプション2", variable=selected_option, value="オプション2")
radio2.pack(pady=5)
# 選択内容を表示するボタン
def show_selection():
print(f"選択されたオプション: {selected_option.get()}")
button = ctk.CTkButton(app, text="選択内容を確認", command=show_selection)
button.pack(pady=10)
# アプリを実行
app.mainloop()
ラジオボタンを作成している箇所に関する説明です.
1.ラジオボタンの作成
# ラジオボタンを作成
radio1 = ctk.CTkRadioButton(app, text="オプション1", variable=selected_option, value="オプション1")
radio1.pack(pady=5)
radio2 = ctk.CTkRadioButton(app, text="オプション2", variable=selected_option, value="オプション2")
radio2.pack(pady=5)
1.1.CTkRadioButtonクラスを使ったラジオボタンの作成
CTkRadioButtonクラスを使ってラジオボタンを作成します.appでボタンをメインウィンドウに設定します."text=…"ではボタン付近に表示させるテキストを設定します.また,選択されたラジオボタンの状態"variable"を
"selected_option"として設定し,ボタンが選択されたときにvariableに格納される値を"value="オプション1"で設定しています.
1.2.ラジオボタンの配置
作成したプログレスバーを"radio1.pack(pady=5)"で配置します.

2.ボタンを作成
今回は,ラジオボタンを選択後にその値をコンソールに出力できるようにしました.
# 選択内容を表示するボタン
def show_selection():
print(f"選択されたオプション: {selected_option.get()}")
button = ctk.CTkButton(app, text="選択内容を確認", command=show_selection)
button.pack(pady=10)
2.1.ボタンが押された後の動作の設定
1.1で定義したラジオボタンの状態"selected_option"を取得し,コンソールに出力するのが"show_selection():"関数です.
2.2.ボタンの作成
ボタンを作成します.詳しくは1の「基本的なプログラムの作成」を参考にしてください.

プログレスバーの作成例
プログレスバーの作成例です.
import customtkinter as ctk
# アプリ設定
app = ctk.CTk()
app.geometry("400x200")
app.title("CTkProgressBar の例")
# プログレスバーを作成
progress_bar = ctk.CTkProgressBar(app, width=300)
progress_bar.pack(pady=20)
# プログレスバーの値を設定
progress_bar.set(0.5) # 値を 0.0 (0%) から 1.0 (100%) に設定
# アプリを実行
app.mainloop()
プログレスバーを作成している箇所に関する説明です.
1.プログレスバーの作成
# プログレスバーを作成
progress_bar = ctk.CTkProgressBar(app, width=300)
progress_bar.pack(pady=20)
1.1.CTkProgressBarクラスを使ったプログレスバーの作成
CTkProgressBarクラスを使ってプログレスバーを作成します.appでスイッチをメインウィンドウに設定します.また,プログレスバーの幅を300ピクセルとして設定します.
1.2.プログレスバーの配置
ウインドウ内に作成したプログレスバーを"progress_bar.pack(pady=20)"で配置します.
2.プログレスバーの値を設定
プログレスバーはバッテリ電圧など何かしら変化のある値を取得して表示させることが多いですが,今回は単純にプログラム内で値を固定させます.
# プログレスバーの値を設定
progress_bar.set(0.5) # 値を 0.0 (0%) から 1.0 (100%) に設定

タブビューの作成
タブビューの作成例です.
import customtkinter as ctk
# アプリ設定
app = ctk.CTk()
app.geometry("400x300")
app.title("CTkTabview の例")
# タブビューを作成
tabview = ctk.CTkTabview(app, width=300, height=200)
tabview.pack(pady=20)
# タブを追加
tabview.add("タブ1")
tabview.add("タブ2")
tabview.add("タブ3")
# タブにウィジェットを追加
tab1_label = ctk.CTkLabel(tabview.tab("タブ1"), text="これはタブ1です")
tab1_label.pack(pady=10)
tab2_label = ctk.CTkLabel(tabview.tab("タブ2"), text="これはタブ2です")
tab2_label.pack(pady=10)
tab3_label = ctk.CTkLabel(tabview.tab("タブ3"), text="これはタブ3です")
tab3_label.pack(pady=10)
# アプリを実行
app.mainloop()
タブビューの箇所に関する説明です.
1.タブビューの作成
# タブビューを作成
tabview = ctk.CTkTabview(app, width=300, height=200)
tabview.pack(pady=20)
# タブを追加
tabview.add("タブ1")
tabview.add("タブ2")
tabview.add("タブ3")
1.1.CTkTabviewクラスを使ったタブビューの作成
CTkTabviewクラスを使ってタブビューを作成します.appでタブビューをメインウィンドウに設定します.またタブビューの寸法もピクセル単位で設定します.
1.2.タブビューの配置
ウインドウ内に作成したタブビューを"tabview.pack(pady=20)"で配置します.
1.3.タブの追加
表示させるタブを"tabview.add"を使って追加します.
2.各タブ内の設定
各タブ内の設定を行います.今回は単純に文字列を表示させています.
# タブにウィジェットを追加
tab1_label = ctk.CTkLabel(tabview.tab("タブ1"), text="これはタブ1です")
tab1_label.pack(pady=10)
tab2_label = ctk.CTkLabel(tabview.tab("タブ2"), text="これはタブ2です")
tab2_label.pack(pady=10)
tab3_label = ctk.CTkLabel(tabview.tab("タブ3"), text="これはタブ3です")
tab3_label.pack(pady=10)

スクロールバーの作成
スクロールバーの作成例です.プログレスバーの作成例です.
import customtkinter as ctk
# アプリ設定
app = ctk.CTk()
app.geometry("400x300")
app.title("CTkScrollableFrame の例")
# スクロール可能なフレームを作成
scrollable_frame = ctk.CTkScrollableFrame(app, width=300, height=200)
scrollable_frame.pack(pady=20)
# スクロール可能なフレームにウィジェットを追加
for i in range(20):
label = ctk.CTkLabel(scrollable_frame, text=f"項目 {i + 1}")
label.pack(pady=5, padx=5)
# アプリを実行
app.mainloop()
スクロールバーを作成している箇所に関する説明です.
1.スクロールバーの作成
# スクロール可能なフレームを作成
scrollable_frame = ctk.CTkScrollableFrame(app, width=300, height=200)
scrollable_frame.pack(pady=20)
1.1.CTkScrollableFrameクラスを使ったプログレスバーの作成
CTkScrollableFrameクラスを使ってスクロールバーを作成します.appでスクロールバーをメインウィンドウに設定します.また,スクロールバーの幅を300ピクセル,高さを200ピクセルとして設定します.
1.2.スクロールバーの配置
作成したスクロールバーを"scrollable_frame.pack(pady=20)"で配置します.
2.スクロールバーの項目設定
スクロールバーの項目を設定します.今回はfor文を使って20個の項目を設定しました.
# スクロール可能なフレームにウィジェットを追加
for i in range(20):
label = ctk.CTkLabel(scrollable_frame, text=f"項目 {i + 1}")
label.pack(pady=5, padx=5)

画像の表示方法
任意の画像を表示させる方法です.
import customtkinter as ctk
from PIL import Image
# アプリ設定
app = ctk.CTk()
app.geometry("400x300")
app.title("CTkImage の例")
# 画像を読み込む
image = ctk.CTkImage(Image.open(r"file_PATH"), size=(200, 200))
# ラベルに画像を表示
label = ctk.CTkLabel(app, image=image, text="")
label.pack(pady=20)
# アプリを実行
app.mainloop()
画像を表示させる箇所に関する説明です.
1.必要ライブラリのインポート
PILライブラリをインポートします.PILは画像を操作するためのライブラリです.
from PIL import Image
2.画像の読み込み
CTkImageクラスを使って画像を読み込み,sizeで画像サイズを指定しています."file_PATH"の箇所は任意の画像のパスに書き換えてください.
# 画像を読み込む
image = ctk.CTkImage(Image.open(r"file_PATH"), size=(200, 200))
【注意点】
Windowsではパス内でバックスラッシュ"\"を使いますが,MacOSではスラッシュ"/"を使う関係で,上の例だとエラーが出ると思います.その場合は以下のように書き換えてください.
# 画像を読み込む
image = ctk.CTkImage(Image.open("file_PATH"), size=(200, 200))

その他の応用例
リアルタイムデータのグラフ化
リアルタイムで取得したデータをグラフ化するプログラムです.実用する際にはCanSatなどからの信号をPCに取り込んでグラフ化すると思いますが,今回はランダムに値を生成しています.
import customtkinter as ctk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import random
import time
import threading
import matplotlib
matplotlib.rcParams['font.family'] = 'Yu Gothic'
class Application(ctk.CTk):
def __init__(self):
super().__init__()
self.title("リアルタイムグラフ")
self.geometry("800x600")
self.running = False
# matplotlibの配置用フレーム
frame = ctk.CTkFrame(self)
frame.pack(fill="both", expand=True)
# matplotlibの描画領域作成
self.fig = Figure()
self.ax = self.fig.add_subplot(1, 1, 1)
self.ax.set_title("リアルタイムグラフ")
self.ax.set_xlabel("時間 (秒)")
self.ax.set_ylabel("値")
self.x_data = []
self.y_data = []
# matplotlibのキャンバスをCustomTkinterフレームに配置
self.fig_canvas = FigureCanvasTkAgg(self.fig, frame)
self.fig_canvas.get_tk_widget().pack(fill="both", expand=True)
# ツールバーを追加
self.toolbar = NavigationToolbar2Tk(self.fig_canvas, frame)
self.toolbar.update()
# ボタンを配置
button_frame = ctk.CTkFrame(self)
button_frame.pack(side="bottom", fill="x", pady=10)
self.start_button = ctk.CTkButton(button_frame, text="グラフ開始", command=self.start_graph)
self.start_button.pack(side="left", padx=10)
self.stop_button = ctk.CTkButton(button_frame, text="グラフ停止", command=self.stop_graph)
self.stop_button.pack(side="left", padx=10)
def start_graph(self):
if not self.running: # グラフが停止中の場合のみ実行
self.running = True
threading.Thread(target=self.run_gengraph, daemon=True).start()
def stop_graph(self):
self.running = False
def run_gengraph(self):
start_time = time.time()# 開始時間
x_min = 0
x_max = 20
self.ax.set_xlim(x_min, x_max)
while self.running:
# データをランダムに生成
current_time = time.time() - start_time# 経過時間
self.x_data.append(current_time)
self.y_data.append(random.uniform(0, 10))
# 表示範囲内のデータのみ抽出
visible_x = [x for x in self.x_data if x_min <= x <= x_max]
visible_y = self.y_data[-len(visible_x):] # xの数に対応するyを取得
# x軸の範囲を動的に更新
if current_time >= x_max:# x_maxを超えたらx_minとx_maxを更新
x_min += 0.5# x_minを0.5増加
x_max += 0.5# x_maxを0.5増加
self.ax.set_xlim(x_min, x_max)
# 横軸のラベルを更新
self.ax.set_xticks(range(int(x_min), int(x_max) + 1, 10))
self.ax.set_xticklabels([f"{tick} 秒" for tick in range(int(x_min), int(x_max) + 1, 10)])
# データを描画
self.ax.clear()
self.ax.plot(visible_x, visible_y, color="blue")
self.ax.set_title("リアルタイムグラフ")
self.ax.set_xlabel("時間 (秒)")
self.ax.set_ylabel("値")
# 描画を更新
self.fig_canvas.draw()
# 待機
time.sleep(0.1) # 0.1秒間隔で更新
# CustomTkinterアプリの起動
if __name__ == "__main__":
ctk.set_appearance_mode("System") # 外観モードを設定 (Dark, Light, System)
ctk.set_default_color_theme("blue") # カラーテーマを設定
app = Application()
app.mainloop()
現在地のマッピング
"TkinterMapView"を用いて現在地を地図上にマッピングすることができます.pipコマンドで"TkinterMapView"をインストールしてください.
pip install TkinterMapView
実用する際には,GNSSセンサからの値を使うことになりますが今回はランダムに座標を生成しています.
import customtkinter as ctk
from tkintermapview import TkinterMapView
import random # GNSSのシミュレーション用
class GNSSApp(ctk.CTk):
def __init__(self):
super().__init__()
self.title("GNSS座標プロットアプリ")
self.geometry("800x600")
# 地図ウィジェットの作成
self.map_widget = TkinterMapView(self, width=800, height=500, corner_radius=0)
self.map_widget.pack(fill="both", expand=True)
# ボタンフレーム
button_frame = ctk.CTkFrame(self)
button_frame.pack(fill="x", pady=10)
# 「現在地更新」ボタン
self.update_button = ctk.CTkButton(button_frame, text="現在地を更新", command=self.update_location)
self.update_button.pack(side="left", padx=10)
# 初期表示の座標
self.current_lat = 35.6809591 # 東京駅の緯度
self.current_lon = 139.7673068 # 東京駅の経度
# 地図を初期表示
self.map_widget.set_position(self.current_lat, self.current_lon)
self.map_widget.set_zoom(15) # ズームレベル
def update_location(self):
# 現在地をランダムにシミュレート(実際にはGNSSデータ取得のコードに置き換えてください)
self.current_lat += random.uniform(-0.005, 0.005) # 緯度を微調整
self.current_lon += random.uniform(-0.005, 0.005) # 経度を微調整
# 現在地を地図にプロット
self.map_widget.set_position(self.current_lat, self.current_lon) # 地図を移動
self.map_widget.set_marker(self.current_lat, self.current_lon, text="現在地")
if __name__ == "__main__":
ctk.set_appearance_mode("System")
ctk.set_default_color_theme("blue")
app = GNSSApp()
app.mainloop()
まとめ
今回はCustomTkinterを使ったGUI画面の基本的な作成方法の備忘録でした.備忘録にまとめると情報が整理できていいですね.