3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

tkinterにアイコンをつけてexeにする

Last updated at Posted at 2025-02-28

【目的】
tkinterで作ったアプリをexeにして配布したい
→どうせならデフォルトのアイコンではなく、好きなアイコンを設定してみたい

【環境】
Windows11
Python 3.12.8

目次

1. 動くものを作る
2. Pyinstallerでexeにする
3. exeにアイコンをつける
4. tkinter GUIにアイコンをつける
5. GUIにアイコンを付けたままexeにする
6. 簡単に解説
7. ソース

1. 動くものを作る

好きなものを作る。
簡単にカウンターアプリでも。

main.py
import tkinter as tk

def CountDown():
    count["text"] = count["text"] - 1

def CountUp():
    count["text"] = count["text"] + 1

root = tk.Tk()
root.title("Counter")
root.geometry("220x100")

count = tk.Label(root, text=0, font=("normal", 20))
count.pack()
tk.Button(root, text=(""), font=("normal", 20), command=CountUp).pack(
    side=tk.LEFT, padx=20, pady=5
)
tk.Button(root, text=(""), font=("normal", 20), command=CountDown).pack(
    side=tk.RIGHT, padx=20, pady=5
)

root.mainloop()

この段階でpython main.pyとすると、tkinterのGUIアイコンはデフォルトの羽マークになる。
image.png

2. Pyinstallerでexeにする

以下のコマンドでexeファイルを作成できる。

terminal
pyinstaller main.py --onefile --noconsole

exeファイル一つだけで動くようにしたいので
--onefile:ファイルを一つにまとめる
--noconsole:コンソールを出さない
のオプションを指定する

上記コマンドにて作成したexeはデフォルトアイコンになる
image.png
作成したexeを実行するとタスクバーは羽マークが表示される
image.png
tkinterのGUIアイコンはデフォルトの羽マークのまま変わらない

現時点でのspecファイルはこんな感じ

main.spec
# -*- mode: python ; coding: utf-8 -*-


a = Analysis(
    ['main.py'],
    pathex=[],
    binaries=[],
    datas=[],
    hiddenimports=[],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    noarchive=False,
    optimize=0,
)
pyz = PYZ(a.pure)

exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.datas,
    [],
    name='main',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    upx_exclude=[],
    runtime_tmpdir=None,
    console=False,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
)

specファイルが既にある場合、

terminal
pyinstaller main.spec

で前回に叩いたコマンドと同じ内容でexeを再生成することができる。

specファイルのあれこれについては別途記事として後日記載予定

3. exeにアイコンをつける

exeのアイコンを任意の画像にするために、コマンドの場合--icon=[ファイルパス]オプションを使用してアイコンを指定する

terminal
pyinstaller main.py --onefile --noconsole --icon=icon.ico

上記コマンドを実行時、specファイルは以下になる。

main.spec
# -*- mode: python ; coding: utf-8 -*-


a = Analysis(
    ['main.py'],
    pathex=[],
    binaries=[],
    datas=[],
    hiddenimports=[],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    noarchive=False,
    optimize=0,
)
pyz = PYZ(a.pure)

exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.datas,
    [],
    name='main',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    upx_exclude=[],
    runtime_tmpdir=None,
    console=False,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
    icon=['icon.ico'],
)

exe = EXE() の末尾にiconが指定される。
specファイルを変更してpyinstaller main.specを実行してもいい。

作成されたexeアイコンは指定した画像になる
←before after→
image.png image.png
※実行時のタスクバーのアイコンは変わらない

4. tkinter GUIにアイコンをつける

root.iconbitmap(default="icon.ico")でtkinterのGUIにアイコンをつける
アイコンファイルは拡張子を.icoにしただけだと表示されないのでしっかりとコンバートする必要がある

main.py
import tkinter as tk

def CountDown():
    count["text"] = count["text"] - 1

def CountUp():
    count["text"] = count["text"] + 1

root = tk.Tk()
root.title("Counter")
root.geometry("220x100")
root.iconbitmap(default="icon.ico")

count = tk.Label(root, text=0, font=("normal", 20))
count.pack()
tk.Button(root, text=(""), font=("normal", 20), command=CountUp).pack(
    side=tk.LEFT, padx=20, pady=5
)
tk.Button(root, text=(""), font=("normal", 20), command=CountDown).pack(
    side=tk.RIGHT, padx=20, pady=5
)

root.mainloop()

これでtkinterのGUIアイコンは指定したicoになる
image.png

5. GUIにアイコンを付けたままexeにする

この状態でpyinstaller main.specを叩いて生成したexeを実行すると、エラーになる
image.png

今のspecファイルではアイコンファイルを取り込んでおらず、また取り込んだとしてもexe実行時はファイルパスが変わるため、このままでは表示できない。

そのためにまずexeからも参照できるようにコードを変更する

main.py
import os
import sys
import tkinter as tk


def CountDown():
    count["text"] = count["text"] - 1


def CountUp():
    count["text"] = count["text"] + 1


root = tk.Tk()
root.title("Counter")
root.geometry("220x100")

iconfile = "icon.ico"
if getattr(sys, "frozen", False):
    iconfile = os.path.join(sys._MEIPASS, iconfile)
root.iconbitmap(default=iconfile)

count = tk.Label(root, text=0, font=("normal", 20))
count.pack()
tk.Button(root, text=(""), font=("normal", 20), command=CountUp).pack(
    side=tk.LEFT, padx=20, pady=5
)
tk.Button(root, text=(""), font=("normal", 20), command=CountDown).pack(
    side=tk.RIGHT, padx=20, pady=5
)

root.mainloop()

main.pyの変更後、

pyinstaller main.py --onefile --noconsole --icon=icon.ico --add-data="icon.ico;."

もしくはspecファイルを以下に変更してpyinstaller main.specを実行する

main.spec
# -*- mode: python ; coding: utf-8 -*-


a = Analysis(
    ['main.py'],
    pathex=[],
    binaries=[],
    datas=[('icon.ico', '.')],
    hiddenimports=[],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    noarchive=False,
    optimize=0,
)
pyz = PYZ(a.pure)

exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.datas,
    [],
    name='main',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    upx_exclude=[],
    runtime_tmpdir=None,
    console=False,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
    icon=['icon.ico'],
)

この時、
・exeのアイコン
・exe実行時のタスクバーのアイコン
・exe実行時のGUIアイコン
が全て任意指定したアイコン画像になる

image.png image.png
image.png

完成!

6. 簡単に解説

  1. pyinstaller
    --add-data datas=[('icon.ico', '.')]にて、icon.icoというファイルをパス.に取り込むという処理をしている
  2. main.py
    以下の部分にて、ファイル呼び出し時にexeからだと以下のIF文がTrueになるため、exe内に取り込んだ画像を呼びだすようにしている
    main.py
    iconfile = "icon.ico"
    if getattr(sys, "frozen", False):
        iconfile = os.path.join(sys._MEIPASS, iconfile)
    root.iconbitmap(default=iconfile)
    

これら2つの処理によって、exe実行時もmain.py実行時もアイコンがしっかりと表示されるようになる

7. ソース

最終状態のものをアップしておきます。
参考になれば幸いです。

3
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?