CustomTkinterでGUIアプリを作成する

2024/04/15

python プログラミング

 普段GUIアプリをpythonで作成する際はTkinterというGUIのライブラリを使用しています。Tkinterはシンプルなデザインなので、最低限自分で使うGUIを作るという観点では機能として十分なのですが、もう少しおしゃれなGUIを作りたい場合にCustomTkinterというものがあるみたいです。

今回はCustomTkinterを使ってみたので、使い方を簡単にまとめてみました。

開発環境

・Windows10
・python 3.9.15
・CustomTkinter 5.2.2

CunstomTkinterのインストール/チュートリアル

CustomTkinterのインストール

まず最初にCustomTkinterをインストールします。
CustomTkinterのインストールはpipコマンドを使って以下のコマンドインストールできます。
pip install customtkinter

チュートリアル

CustomTkinterの公式ドキュメントは下記のリンク先です。
公式ドキュメント内にチュートリアルがあるため、まずはそれを実行してみます。
サンプルコードのそれぞれの行の意味についてはコメントに記載したので、参考にしてみてください。

# ライブラリのインポート箇所
# ----------------------------------------------------------------------------------
import customtkinter
# -------------------------------------------------

def button_callback(): #  ボタンを押した際の動作の定義
    print("button pressed")

app = customtkinter.CTk()
app.title("my app") #  画面のタイトル名
app.geometry("400x150") #  画面の大きさの規定

button = customtkinter.CTkButton(app, text="my button", command=button_callback) #  ボタンの定義。textでボタンに表示される名前を規定。commandでボタンを押した際に呼び出す関数の設定
button.grid(row=0, column=0, padx=20, pady=20) #  ボタンの配置の規定

app.mainloop() #  画面を出し続けるためのおまじない

実行結果がこちらです。

タイトルに先ほど設定した"myapp"という言葉が入っており、mybuttonというボタンも作られています。こちらのボタンを押すと button pressedとコマンドライン上に表示されていることが分かります。


グリッドジオメトリの設定

続いてグリッドジオメトリの設定を行います。ジオメトリーマネージャーを使うことで、ウィジェットの位置とパディングを設定できます。

上記説明だけだと意味が分からないと思うので、具体例で見てみます。
先ほどのコードに下記のコードを追加します。
app.grid_columnconfigure(0, weight=1)# 0列目の要素を重み1とする
この設定をすることで、ボタンを列の中央に設定することが出来ます。また、画面を拡大縮小した際に常にボタンの要素が真ん中に来るようになります。

また、今回はColumnのweightを設定しているため、横方向はボタンのサイズより小さくすることが出来なくなってます。縦方向はweightの設定をしていないため、ボタンサイズより小さくすることが出来るようになってます。

また、Weihtについてですが、今回は1つの要素しかないため、あまり意味が無いですが、2つ以上の要素がある場合に、重みの比率で要素の大きさを決めることが出来るみたいです。
具体的な説明は下記のサイトのGridderのリサイズを参照お願いします。

続いてボタンのグリッドの設定していきます。チュートリアルでは下記コードを追加してます。
button.grid(row=0, column=0, padx=20, pady=20, sticky="ew")
padx,padyはボタンの外側の余白をどのくらい用意するかの設定となります。stickyはGrid内のどこにボタンを配置するかという設定なので通常は東西南北(E,W,S,N)、の4つの方向を示すのですが、"ew"という設定をした場合は画面拡大時に左右も大きくなるという設定になります。(縦方向に伸ばしたい場合は"ns"と指定します。)



ラジオボタンを追加する

続いてもうすこし複雑な構造にするためにチェックボックスを追加します。下記のコードを追加します。
checkbox_1 = customtkinter.CTkCheckBox(app, text="checkbox 1")#チェックボックス1の名前を入力
checkbox_1.grid(row=1, column=0, padx=20, pady=(0, 20), sticky="w")#チェックボックス1の配置を決める(column(列を0番目に配置))
checkbox_2 = customtkinter.CTkCheckBox(app, text="checkbox 2")#チェックボックス2の名前を入力
checkbox_2.grid(row=1, column=1, padx=20, pady=(0, 20), sticky="w")#チェックボックス1の配置を決める(column(列を1番目に配置))

実行結果がこちらです。チェックボックスが追加されました。
先ほどまではmy buttonが真ん中にありましたが、2列になって0列目の場所になったため、check box1と左端がそろった場所に配置されるようになったことが分かります。

このままだとmy buttonの見栄えが悪いため、my buttonをウィンドウ全体に広げます。
やり方は先ほど規定したbutton.gridの引数にcolumnspanの引数を追加して2を設定します。これはこのボタンが2列にまたがって作られることを意味します。
button.grid(row=0, column=0, padx=20, pady=20, sticky = "ew", columnspan = 2) #  ボタンの配置の規定(columnspanを2にすることで2列にまたがるボタンになる)
実行結果がこちらです。my buttonが2列にまたがるようになりました。


今回作成したプログラムをクラス化する

こちらの内容は実施しなくてもいい内容だと思います。大規模なプログラムを作成する場合に可読性を向上させたり、同様の処理を複数作ることが出来るのですが、個人でやる分にはやってもやらなくてもいいと思います。ちなみにpythonのクラスについては下記サイトを参照お願いします。
前置きが長くなりましたが、今まで作成したコードをクラスにしていきます。(このコードはチュートリアルに記載されているコードそのままです。)
# ライブラリのインポート箇所
# -------------------------------------------------
import customtkinter
# -------------------------------------------------
class App(customtkinter.CTk):
    def __init__(self):
        super().__init__()

        self.title("my app")
        self.geometry("400x150")
        self.grid_columnconfigure((0, 1), weight=1)

        self.button = customtkinter.CTkButton(self, text="my button", command=self.button_callback)
        self.button.grid(row=0, column=0, padx=20, pady=20, sticky="ew", columnspan=2)
        self.checkbox_1 = customtkinter.CTkCheckBox(self, text="checkbox 1")
        self.checkbox_1.grid(row=1, column=0, padx=20, pady=(0, 20), sticky="w")
        self.checkbox_2 = customtkinter.CTkCheckBox(self, text="checkbox 2")
        self.checkbox_2.grid(row=1, column=1, padx=20, pady=(0, 20), sticky="w")
        
    def button_callback(self):
        print("button pressed")

app = App()
app.mainloop()
簡単にコードを解説すると、親クラスとしてcustomtikinterの内容を継承して、コンストラクタ内で今回作成した処理を記述してます。

(補足)クラス化してないソースコード

先ほどクラス化したコードを提示しましたが、クラス化する前にいろいろといじったコードも提示しておきます。あくまで参考情報です。

# ライブラリのインポート箇所
# -------------------------------------------------
import customtkinter
# -------------------------------------------------

def button_callback(): #  ボタンを押した際の動作の定義
    print("button pressed")

app = customtkinter.CTk()
app.title("my app") #  画面のタイトル名
app.geometry("400x150") #  画面の大きさの規定
app.grid_columnconfigure((0,1), weight=1)# 0列目の要素を重み1とする

button = customtkinter.CTkButton(app, text="my button", command=button_callback) #  ボタンの定義。textでボタンに表示される名前を規定。commandでボタンを押した際に呼び出す関数の設定
button.grid(row=0, column=0, padx=20, pady=20, sticky = "ew", columnspan = 2) #  ボタンの配置の規定(columnspanを2にすることで2列にまたがるボタンになる)

checkbox_1 = customtkinter.CTkCheckBox(app, text="checkbox 1")#チェックボックス1の名前を入力
checkbox_1.grid(row=1, column=0, padx=20, pady=(0, 20), sticky="w")#チェックボックス1の配置を決める(column(列を0番目に配置))
checkbox_2 = customtkinter.CTkCheckBox(app, text="checkbox 2")#チェックボックス2の名前を入力
checkbox_2.grid(row=1, column=1, padx=20, pady=(0, 20), sticky="w")#チェックボックス1の配置を決める(column(列を1番目に配置))
app.mainloop() #  画面を出し続けるためのおまじない




自己紹介

はじめまして 社会人になってからバイクやプログラミングなどを始めました。 プログラミングや整備の記事を書いていますが、独学なので間違った情報が多いかもしれません。 間違っている情報や改善点がありましたらコメントしていただけると幸いです。

X(旧Twitter)

フォローお願いします!

QooQ