CustomTkinterは、Python の標準 GUI ライブラリである Tkinter をベースに、モダンなデザインのウィジェットや機能を追加した拡張ライブラリです。主な開発者は Tom Schimansky 氏で、2021 年頃にこのプロジェクトを公開し、現在も中心となってメンテナンスを行っています。MIT ライセンスの下で提供されており、個人・商用問わず広く利用可能です。
CustomTkinter は標準の Tkinter と書き方がほぼ同じため、Tkinter ユーザーには学習しやすいツールだと思います。学習曲線が緩やかなのにもかかわらず、「見た目が古臭い」という Tkinter の問題点を解決し、洗練された GUI アプリケーションを開発できることから、人気急上昇中のライブラリです。
CustomTkinter は pip を使って簡単にインストールすることができます。pip は仮想環境下で実行してください。
(.venv) $ pip install customtkinter
M.Hiroi の環境では、customtkinter 5.2.2 がインストールされました (2026 年 2 月時点)。
それでは実際にプログラムを作ってみましょう。ボタンをひとつ表示します。
リスト : ボタンの表示
import customtkinter as ctk
root = ctk.CTk()
button = ctk.CTkButton(root, text = 'Hello, Tkinter', font = ('Noto Sans CJK JP', 16))
button.pack(padx=50, pady=50)
root.mainloop()
最初に customtkinter をインポートして ctk という別名を付けます。次に、CTk() でメインウィンドウを作成します。CTk() は Tkinter の Tk() に相当します。CTk() はクラス CTk のインスタンス (オブジェクト) を生成して返します。このオブジェクトが画面上のメインウィンドウに対応します。
次にボタンを作ります。Tkinter の場合、コンストラクタ Button() でボタンのオブジェクトを生成します。CostumTkinter の場合、Tkinter のコンストラクタの前に CTk を付けたものがコンストラクタになります。ボタンの場合は CTkButton() となります。引数は Tkinter に準じますが、異なるところもあります。
たとえば、フォントのサイズですが、Tkinter ではサイズが正の整数であればポイント単位 (p) に、負の整数であればピクセル単位 (px) になります。CoustomTkinter の場合、サイズはピクセル単位になることに注意してください。
この段階では、ボタンはまだ配置されていません。ボタンの配置はメソッド pack() で行います。Tk (CustomTkinter を含む) の場合、ウィジェットの配置はジオメトリマネージャが行います。3 種類のマネージャがあって、pack() はそのうちのひとつです。button.pack() が実行されると、ウィンドウにボタンが配置されます。
最後にメソッド mainloop() を呼び出して、イベントループを開始します。このように、CustomTkinter のプログラムは Tkinter とほとんど同じであることがわかります。
実行結果を示します。
CustomTkinter のボタン
Tkinter と違って、おしゃれなボタンですね。
CustomTkinterには、ウィジェットのアクセントカラー (ボタンの色など) を一括設定する 3 つの標準テーマが用意されています。
テーマ名 特徴 ----------------------------------------------- "blue" 標準 (デフォルト) の青色テーマ "dark-blue" 落ち着いた深みのある青色テーマ "green" 緑色のアクセントテーマ
カラーテーマを設定するには関数 set_default_color_theme() を使います。green に設定する例を示します。
リスト : カラーテーマの設定例
import customtkinter as ctk
ctk.set_default_color_theme("green")
実行結果は次のようになります。
CustomTkinter のボタン (green)
CustomTkinter のカラーテーマはカスタマイズすることが可能です。.json 形式のテーマファイルを作成し、set_default_color_theme() で読み込みます。既存のテーマ (blue, dark-blue, green) をコピーし、カラーコードを書き換えるのが最も簡単でしょう。興味のある方は実際に試してみてください。
CustomTkinterでは、関数 set_appearance_mode() を使用して、外観モード (ダークモード / ライトモード) を簡単に切り替えることができます。主なモード設定は以下 の 3通りです。
"System" OS の設定に従う (デフォルト, Windows / macOS) "Light" 明るい背景 (白ベース) "Dark" 暗い背景 (黒・ダークグレーベース)
System は OS のライト / ダークモード設定を自動的に反映します。実行中に OS 側でモードを切り替えると、アプリの見た目も追従します。Dark はアプリを常にダークモードで表示します。Light はアプリを常にライトモードで表示します。Linux で System を選択した場合、現時点ではシステム設定を正しく読み込めず、常にライトモードになる制限があります。
リスト : Appearance Mode の設定
import customtkinter as ctk
ctk.set_appearance_mode("Dark")
実行例を示します。
CustomTkinter のボタン (Dark Mode)
また、ウィジェットで色を指定するとき、(ライトモード用, ダークモード用) のタプルで指定すると、外観モードの切り替え時に自動で色が反映されます。たとえば、ボタンのテキストの色は、Tkinter では fg で指定しますが、CustomTkinter では text_color で指定します。text_color にタプルを指定すると、最初の要素がライドモードの色、二番目の要素がダークモードの色になります。
簡単な例を示しましょう。
リスト : ウィジェットの色指定
import customtkinter as ctk
ctk.set_appearance_mode("Light") # System, Dark, Light
root = ctk.CTk()
button = ctk.CTkButton(root, text = 'Hello, Tkinter',
text_color = ('black', 'yellow'), font = ('Noto Sans CJK JP', 16))
button.pack(padx=50, pady=50)
root.mainloop()
CustomTkinter のボタン (Light Mode)
CustomTkinter のボタン (Dark Mode)
このように、Light Mode では文字の色が黒色に、Dark Mode では黄色になります。
GUI アプリケーションの場合、ユーザーからの入力やシステムの状態変化など、ある出来事をきっかけにプログラムが実行されます。この出来事を「イベント (event)」といい、イベントをきっかけにしてプログラムが起動されることを「イベントドリブン (eventdriven : イベント駆動)」といいます。イベントドリブン型のアプリケーションは、一般に次のようなメインルーチンを持っています。
2 から 4 を「イベントループ」と呼び、アプリケーションはユーザーからの入力などのイベントを待ちます。そして、3 の処理に対応する機能が「バインディング (binding)」です。バインディングは、ウィンドウでイベントが発生したときに、それに応じて定義したプログラムを実行します。このプログラムを「イベントハンドラ」とか「コールバック関数」と呼びます。
GUI アプリケーションとしての最低限の機能は Tk (Tkinter, Customkinter) が面倒を見てくれるので、私達はアプリケーション固有の処理をプログラミングするだけで済みます。
Tk で GUI アプリケーションを作る場合、次のような手順が必要になります。
このほかに、必要に応じてコールバック関数を作成します。Tcl/Tk の場合、1 と 3 の処理はプログラムする必要はありませんが、CustomTkinter では自分でプログラムを記述します。
ウィジェットは次の形式で生成します。
widget = widgetClass(parent, option = value, .... )
これで parent に配置するウィジェットが生成されます。parent にはメインウィンドウやほかのウィジェットのオブジェクト、widgetClass には生成するウィジェットのクラス名を指定します。返り値は生成したウィジェットのオブジェクトです。メインウィンドウもウィジェットのひとつですが CTk() で生成します。
ボタンの例題のように、ウィジェットにはユーザーがデータを設定することができます。これを「オプション」といいます。最初に、ほとんどのウィジェットで共通するオプションを説明します。
ウィジェットの幅と高さは、テキストを表示するウィジェットでは文字数、それ以外のウィジェットはピクセル単位となります。オプションは option = value の形式で指定します。
オプションはウィジェットを生成するときに指定しますが、メソッド configure() を使って、あとからオプションの値を変更することもできます。また、オプションの値を参照するにはメソッド cget() を使います。
widget.configure(option = value, ...) widget.cget(option_name)
cget() の引数 option_name はオプションを指定する文字列です。configure() と cget() は全てのウィジェットで使用することができます。Tkinter では、このようなウィジェットを操作するメソッドが多数用意されています。ちなみに、Tcl/Tk ではウィジェットを操作するメソッドのことを「ウィジェットコマンド」と呼びます。
最初は簡単に扱えるボタン (CTkButton) とラベル (CTkLabel) から始めましょう。ラベルはウィンドウに文字列を表示するウィジェットです。まず、ボタンとラベルでよく使用されるオプションを示します。
ボタンにはもうひとつ重要なオプションがあります。
command 押したときに実行する関数を指定
たとえば、command に Python を終了する関数 exit() を指定し、そのボタンを押すとアプリケーションが終了することになります。このような関数を「コールバック関数」と呼びます。Python の場合、引数に関数を渡すのは簡単にできますが、ボタンの command で指定した関数は引数無しで呼び出されることに注意してください。たとえば、exit() に引数を渡して終了する場合は、次のように指定します。
Button(root, text = 'Python/Tkinter', command = lambda : sys.exit(1))
ラムダ形式を使うと簡単に指定することができます。引数が不要の場合は command = sys.exit でもかまいません。
ボタンを作ったら、それをウィンドウに配置しないといけません。Tk (Tkinter, CustomTkinter) ではジオメトリマネージャ (Geometry Manager) がウィジェットの配置を担当し、3 種類のマネージャが用意されています。
いちばんよく使われるマネージャが Packer です。Placer はウィジェットの位置を座標で指定するため、並べて表示する場合には設定が少々面倒です。たいていの場合は Packer で用が足りるので、Placer を使う機会はあまりないでしょう。電卓やマインスイーパーのように、ボタンを格子状に配置する場合は Gridder が便利です。
それでは簡単な例題として、押したボタンの番号をラベルに表示するプログラムを作ります。次のリストを見てください。
リスト : ボタンとラベル
import customtkinter as ctk
root = ctk.CTk()
root.geometry("200x200")
my_font = ('Noto Sans CJK JP', 12)
buff = ctk.StringVar()
buff.set("")
# ラベルの生成
label = ctk.CTkLabel(root, textvariable = buff, font = my_font)
label.pack(pady=4)
# コールバック関数の生成
def make_cmd(n):
return lambda : buff.set(f'button {n} pressed')
# ボタンの生成
for x in range(4):
button = ctk.CTkButton(root, text = f'Button {x}', command = make_cmd(x), font = my_font)
button.pack(padx=4, pady=4)
root.mainloop()
geometry メソッドは、メインウィンドウやサブウィンドウのサイズ (幅と高さ) および表示位置を指定するために使用されます。 引数には "幅x高さ+X座標+Y座標" という形式の文字列を渡します。オプション textvariable には Tkinter と同様にクラス Variable のオブジェクトを指定します。
具体的にはサブクラス IntVar, DoubleVar, StringVar, BooleanVar を使います。文字列の場合は StringVar() でオブジェクトを生成します。メソッド set() でデータをセットし、メソッド get() でデータを得ることができます。値を書き換えることで、ラベルの表示を変更することができます。
次はボタンを作ります。複数のボタンを作る場合、それに対応するコールバック関数を同じ数だけ作るのでは面倒です。そこで、コールバック関数を生成する関数をひとつだけ作成し、それにボタンの番号を渡すことにします。
関数 make_cmd() でコールバック関数を生成します。make_cmd() はクロージャを返すことに注意してください。make_cmd() の引数 n にボタン番号を渡すことで、ボタン番号がクロージャに保存されます。したがって、コールバック関数を実行すると、押したボタンの番号を表示することができます。
それでは実行してみてください。
button 0 を押した動作
ボタンが縦に 4 つ表示されましたね。そして、ボタンを押すといちばん上に文字列が表示されます。つまり、ボタンを押すという動作によってプログラムが実行されたわけです。
次は pack() について説明しましょう。pack() はウィジェットを上から順に詰め込み、ウィンドウに配置するパッケージマネージャです。例題ではボタンの幅がウィンドウより小さいですが、これをいっぱいに広げるには fill オプションを使います。方向は 'x', 'y' で指定します。両方向に広げるには 'both' を指定します。実際に fill を追加して確かめてください。
fill = 'x' を指定し、button 2 を押した動作
詰め込む方向を変えるにはオプション side を使います。指定できる値は 'top', 'bottom', 'left', 'right' の 4 つです。ウィジェットによって詰め込む方向を変えてもかまいません。geometry() を削除して、ボタンを配置する pack に side = 'left' を追加して実行してみましょう。一番上にラベルが配置され、その下にボタンが 4 つ左から順番に並べられます。
side = 'left' を指定し、button 3 を押した動作
このとき、ラベルはウィンドウの中央に表示されます。これを左側に寄せるには anchor オプションを設定します。指定が省略された場合は中央になります。指定方法は次の記号を使います。
nw --- n --- ne | | w c e | | sw --- s --- se
記号はそれぞれ 'e' (East), 'w' (West), 's' (South), 'n' (North), 'c' (Center) を表します。ラベルを pack するときに、オプション anchor = 'w' を指定すると左寄せに表示します。
anchor = w を指定し、button 0 を押した動作
このほかにも、 pack() にはいろいろなオプションが用意されています。
今回はテキストやボタンに色をつけてみましょう。Tk の場合、色の指定は名前または数値で行います。名前は red, green, blue のように指定します。色の名前は大文字小文字の区別をしません。red と RED は同じ色を表します。数値の場合は、赤、緑、青の三原色を 16 進数で指定します。指定方法には、次の 4 通りの形式があります。
色の指定は # から始まり、R, G, B はそれぞれ赤、緑、青の強度を表す数値です。それぞれの色を表す桁数は同じでなければいけません。1. では、R, G, B が 16 段階なので 4096 色の指定ができます。2. は 256 段階なので、約 1600 万色の指定ができます。3. 4. はほとんど使われることはないでしょう。実際の表示は使用しているハードウェアの環境に依存します。
それでは、R, G, B の値で色がどのように変化するか、サンプルプログラムを作って確かめてみましょう。数値の入力はキーボードから行ってもいいのですが、ここでは「スライダー (CtkSlider)」というウィジェットを使いましょう。スライダーは従来の Tkinter の「Scale(スケール)」に相当するウィジェットです。モダンなデザインで、スライダーを動かすことで数値を選択・取得できます。主なオプションを以下に示します。
form_ と to で値の範囲を指定します。from は Ptyhon のキーワードなので、CustomTkinter では from_ を使います。orientation (orient でもよい) はスケールの方向を指定するもので、horizontal または h を指定すると水平になり、vertical または v で垂直になります。デフォルトでは水平に設定されます。
variable はスケールの値を格納する変数を指定しますが、Tkinter ではクラス Variable のオブジェクトを指定します。整数値の場合は IntVar() を使います。command はスケールの値が変更されたときに実行する関数を指定します。このとき、スケールの値が引数として関数に渡されます。たとえば、関数 foo() を指定した場合、呼び出されるときは foo(128) となります。このほかにも、ウィジェットの大きさを設定するオプションがあります。
スライダーには configure() や cget() のほかに、次に示すメソッドが用意されています。
それでは、ボタンの背景色を変化させるプログラムを作ります。
リスト : スライダーの使用例
import customtkinter as ctk
# メインウィンドウ
root = ctk.CTk()
my_font = ('Noto Sans CJK JP', 20)
# スケールの値を格納する
red = ctk.IntVar()
red.set(0)
blue = ctk.IntVar()
blue.set(0)
green = ctk.IntVar()
green.set(0)
# ボタンの背景色を変更
def change_color( n ):
color = '#{:02x}{:02x}{:02x}'.format(red.get(), green.get(), blue.get())
button.configure(fg_color = color)
# ボタン
button = ctk.CTkButton(root, text = 'button', fg_color = '#000', font = my_font)
button.pack(pady=4);
# スライダー
s1 = ctk.CTkSlider(root, from_ = 0, to = 255, variable = red,
button_color = 'red',
command = change_color)
s2 = ctk.CTkSlider(root, from_ = 0, to = 255, variable = blue,
button_color = 'blue',
command = change_color)
s3 = ctk.CTkSlider(root, from_ = 0, to = 255, variable = green,
button_color = 'green',
command = change_color)
# ウィジェットの配置
s1.pack(pady = 10)
s2.pack(pady = 10)
s3.pack(pady = 10)
# メインループ
root.mainloop()
スライダーの値を格納する IntVar のオブジェクトは、それぞれ red, blue, green というグローバル変数にセットします。値は 0 に初期化しておきます。ボタンのオブジェクトは背景色を変更するときに必要になるので、グローバル変数 button に格納しておきます。値が変化したときに実行する関数が change_color() です。
文字列のフォーマット操作を使って red, green, blue の値をカラーコードに変換します。数値を 2 桁にそろえるため、format の書式は :02x としています。その後、ボタンの背景色を configure メソッドで変更します。これで、スライダの動きによってボタンの色を変化させることができます。
スライダで RGB を指定する
今度は色だけではなくフォントも変更してみましょう。フォントの指定にはいくつかの方法があるのですが、Windows や Ubuntu であれば次の形式で行えばいいでしょう。
(family, size, style1, style2)
フォントはタプルを使って指定することができます。family はフォント名を表します。size はフォントの大きさを表し数値で指定します。style1 と style2 はフォントのスタイルで、次の中から選びます。
style1 : normal, bold, roman, italic style2 : underline, overstrike
style1 と style2 は省略することができます。それでは、フォントを変更してみましょう。次のプログラムを見てください。
リスト : フォントの変更
import customtkinter as ctk
root = ctk.CTk()
str = 'Hello, world, こんにちは世界'
ctk.CTkLabel(root, text=str, font=('Noto Sans CJK JP', 20)).pack()
ctk.CTkLabel(root, text=str, font=('Noto Serif CJK JP', 20), text_color = 'blue').pack()
ctk.CTkLabel(root, text=str, font=('Noto Sans CJK JP', 20, 'italic')).pack()
ctk.CTkLabel(root, text=str, font=('Noto Sans Mono CJK JP', 20, 'italic'), text_color ='red').pack()
ctk.CTkLabel(root, text=str, font=('Noto Serif CJK JP', 28, 'underline')).pack()
ctk.CTkLabel(root, text=str, font=('Noto Sans Mono CJK JP', 28, 'underline'), text_color = 'green').pack()
root.mainloop()
テキストを表示するウィジェットは、オプション font で使用するフォントを指定することができます。それでは実行してみましょう。
フォントをいろいろ変えてみる
このように、個々のウィジェットのフォントはオプション font で変更できますが、すべてのラベルウィジェットで使用する共通のフォントを設定したい場合もあるでしょう。Tk (Tcl/Tk や Tkinter) は各オプションのデフォルト値を持っています。このため、ユーザーは必要なオプションを指定するだけで、簡単にプログラミングすることができます。
このデフォルト値はメソッド option_add() を使って変更することができます。ところが、CustomTkinter は option_add() で指定した値を無視します。CustomTkinter の場合、テーマをカスタマイズする方法がありますが、それよりも、ウィジェットクラスを継承したサブクラスを定義し、そこでオプションを設定する方法が簡単だと思います。次のリストを見てください。
リスト : ボタンのフォントと背景色を変更
import customtkinter as ctk
root = ctk.CTk()
my_font = ('Noto Sans CJK JP', 10)
# フォントと色を指定したボタン
class MyButton(ctk.CTkButton):
def __init__(self, *args, **kwargs):
# デフォルトのフォントと背景色を指定
if "font" not in kwargs:
kwargs["font"] = ('Noto Sans Mono CJK JP', 12)
if "fg_color" not in kwargs:
kwargs["fg_color"] = 'darkgreen'
super().__init__(*args, **kwargs)
buff = ctk.StringVar()
buff.set("")
# ラベルの生成
label = ctk.CTkLabel(root, textvariable = buff)
label.pack(anchor = 'w')
# コールバック関数の生成
def make_cmd(n):
return lambda : buff.set('button {} pressed'.format(n))
# ボタンの生成
for x in range(4):
button = MyButton(root, text = 'Button {}'.format(x), command = make_cmd(x))
button.pack(padx = 2, pady = 2, side = 'left')
root.mainloop()
CTkButton を継承したクラス MyButton を定義します。MyButton() で指定したオプションは __init__() の引数 kwargs に渡されます。kwargs に font がない場合、デフォルトのフォントとして ('Noto Sans Mono CJK JP', 12) をセットします。同様に、fg_color がない場合はデフォルトの背景色に 'darkgreen' をセットします。ボタンを MyButton() で生成すると、表示されるボタンのフォントと背景色は、設定された値となります。
ボタンのフォントと背景色を変更