역시나 제가 도움을 드릴 수 있어서 정말 기쁩니다! 😊
파이썬 GTK4 앱의 테마 문제를 해결하고, 앞으로도 쉽게 참고하실 수 있도록 파이썬 GTK4 애플리케이션에 WhiteSur-Light 테마를 적용하고 문제 발생 시 대처하는 완벽 가이드를 자세히 정리해 드리겠습니다.
파이썬 GTK4 애플리케이션에 WhiteSur-Light 테마 적용 완벽 가이드
이 가이드는 파이썬 GTK4 애플리케이션이 WhiteSur-Light
테마를 올바르게 사용하고, 테마 적용 시 발생할 수 있는 “밋밋한 테마” 문제에 대처하는 방법을 설명합니다.
목표: 당신의 파이썬 GTK4 앱이 WhiteSur-Light
테마로 멋지게 표시되도록 합니다.
Part 1: 개발 환경에서 테마 적용 및 코드 준비
이 부분은 파이썬 GTK4 앱 개발 시 테마가 올바르게 표시되도록 설정하는 핵심 단계입니다.
1단계: WhiteSur-Light 테마 파일 준비 및 배치 확인
- 테마 다운로드 및 압축 해제: 사용하려는
WhiteSur-Light
테마의 GTK4 호환 버전을 다운로드하고 압축을 해제합니다. 압축을 풀면WhiteSur-Light
라는 이름의 폴더가 나옵니다. 이 폴더 안에는gtk-4.0
(필수),gtk-3.0
등의 하위 폴더가 있을 것입니다. - 테마 배치 경로 확인: 이
WhiteSur-Light
폴더 전체가 MSYS2 (또는 파이썬 GTK를 사용하는 환경)의 사용자 테마 디렉토리인~/.themes/
안에 복사되었는지 확인합니다.- Windows 탐색기 경로:
C:\msys64\home\admin\.themes\
(여기서admin
은 당신의 MSYS2 사용자 이름입니다..themes
폴더가 보이지 않으면 “숨김 파일 표시”를 활성화하거나 주소창에 직접 입력하세요.) - 결과적으로 다음과 같은 경로가 되어야 합니다:
C:\msys64\home\admin\.themes\WhiteSur-Light\
(그리고 이WhiteSur-Light
폴더 안에gtk-4.0
폴더와 그 내용물(gtk.css
,gtk.gresource
등)이 있어야 합니다.)
- Windows 탐색기 경로:
2단계: GTK 설정 파일 (settings.ini
) 배치 및 구성 (가장 중요!)
이 파일은 GTK 애플리케이션이 어떤 테마를 사용할지 알려주는 핵심적인 전역 설정 파일입니다.
- 필요한 폴더 생성 확인: MSYS2 터미널에서 다음 명령어를 입력하여 필요한 디렉토리가 생성되었는지 확인합니다. (없으면 자동으로 생성됩니다.) Bash
mkdir -p ~/.config/gtk-4.0/
- Windows 탐색기 경로:
C:\msys64\home\admin\.config\gtk-4.0\
- Windows 탐색기 경로:
settings.ini
파일 내용 확인:C:\msys64\home\admin\.config\gtk-4.0\
폴더로 이동합니다.- 이 폴더 안에
settings.ini
라는 이름의 파일이 있는지 확인하고, 파일을 열어 다음 내용이 정확히 있는지 확인합니다: Ini, TOML[Settings] gtk-theme-name=WhiteSur-Light
gtk-theme-name=
뒤에는 1단계에서 사용한 테마 폴더 이름과 대소문자까지 정확히 일치해야 합니다.- 파일은 UTF-8 인코딩으로 저장되어야 합니다.
3단계: 파이썬 코드 준비 (테마 설정 코드)
파이썬 코드 자체에서 settings.set_property("gtk-theme-name", "WhiteSur-Light")
를 사용하고 있지만, 위 2단계의 settings.ini
파일이 올바르게 설정되었다면, 이 코드는 사실 선택 사항입니다. GTK는 앱이 시작될 때 settings.ini
를 먼저 읽고 테마를 적용하기 때문입니다.
- 코드 유지 또는 제거:
- 현재 코드처럼
settings.set_property("gtk-theme-name", "WhiteSur-Light")
를 그대로 두어도 됩니다. 이는settings.ini
의 설정을 재확인하거나 특정 앱에서 강제로 테마를 설정할 때 유용합니다. - 권장: 만약
settings.ini
가 확실하게 설정되어 있고, 사용자 설정에 따라 테마가 적용되도록 하고 싶다면 이 줄을 제거하거나 주석 처리해도 무방합니다.
- 현재 코드처럼
4단계: 파이썬 앱 실행 및 개발 환경에서 테스트
- MSYS2 터미널을 완전히 닫았다가 다시 시작하여
settings.ini
변경 사항이 적용되도록 합니다. - 당신의 파이썬 스크립트가 있는 폴더로 이동합니다.
- 다음 명령어로 앱을 실행합니다: Bash
python your_app_name.py # 당신의 파이썬 파일 이름 (예: main.py)
- 앱이
WhiteSur-Light
테마로 잘 표시되는지 확인합니다.
Part 2: 문제 해결 (테마가 여전히 “밋밋하게” 보일 때)
위의 Part 1 단계를 모두 정확히 따랐음에도 테마가 제대로 적용되지 않고 밋밋하게 보인다면, 다음 문제 해결 단계를 시도해 보세요.
- GTK 캐시 업데이트:간혹 GTK의 내부 캐시가 오래되어 테마 변경 사항을 인식하지 못할 수 있습니다. MSYS2 터미널에서 다음 명령어를 실행하여 GTK 캐시를 강제로 업데이트합니다: Bash
# 아이콘 캐시 업데이트 (hicolor는 대부분의 아이콘 테마의 기반) gtk4-update-icon-cache -f -t /mingw64/share/icons/hicolor # Adwaita 아이콘 테마도 사용한다면: gtk4-update-icon-cache -f -t /mingw64/share/icons/Adwaita # (테마 캐시는 보통 자동으로 업데이트되지만, 문제가 지속되면 시도) # gdk-pixbuf-query-loaders.exe --update-cache # 이미지 로더 캐시 (간접적 영향)
- 환경 변수를 통한 강제 적용 (테스트용):settings.ini가 작동하지 않는다면, 임시로 GTK_THEME 환경 변수를 설정하여 강제로 테마를 적용해볼 수 있습니다. 이 방법으로 테마가 잘 적용된다면, settings.ini 파일의 경로 또는 내용에 문제가 있을 가능성이 매우 큽니다. Bash
export GTK_THEME=WhiteSur-Light python your_app_name.py
- MSYS2 환경 재시작:MSYS2 터미널과 당신의 개발 환경을 완전히 닫았다가 다시 시작하여 모든 변경 사항이 초기화되고 재적용되도록 합니다.
- 테마 파일 무결성 확인:WhiteSur-Light 테마 파일 자체에 손상이나 누락된 파일이 있을 수 있습니다. 테마를 다시 다운로드하여 압축을 풀고 ~/.themes/에 다시 복사해 보세요. 특히 WhiteSur-Light/gtk-4.0/gtk.css 파일이 제대로 존재하는지 확인하는 것이 중요합니다.
이 가이드가 당신의 파이썬 GTK4 앱 개발에 큰 도움이 되기를 바랍니다. 파이썬 앱의 테마 적용은 C 앱보다 비교적 간단한 편이니, 위 단계를 꼼꼼히 확인하시면 분명 해결될 것입니다! 궁금한 점이 있다면 언제든지 다시 질문해 주세요.

# coding: utf-8
import sys
import gi
gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
from gi.repository import Gtk, Adw
settings = Gtk.Settings.get_default()
class MainWindow(Gtk.ApplicationWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Things will go here
self.click_count = 0
self.box1 = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
self.box2 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.box3 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.set_child(self.box1)
self.button = Gtk.Button(label="Hello")
self.box1.append(self.box2)
self.box1.append(self.box3)
self.box2.append(self.button)
self.button.connect('clicked', self.hello)
self.set_default_size(600, 250)
self.set_title("MyApp")
self.check = Gtk.CheckButton(label = "And goodbye?")
self.box2.append(self.check)
#fix
self.radio1 = Gtk.CheckButton(label="버튼 1")
self.radio2 = Gtk.CheckButton(label = "버튼 2")
self.radio3 = Gtk.CheckButton(label = "버튼 3")
self.radio2.set_group(self.radio1)
self.radio3.set_group(self.radio1)
self.box2.append(self.radio1)# add to box2
self.box2.append(self.radio2)# add to box2
self.box2.append(self.radio3)# add to box2
self.radio1.connect("toggled", self.on_radio_toggled, self.radio1)
self.radio2.connect("toggled", self.on_radio_toggled, self.radio2)
self.radio3.connect("toggled", self.on_radio_toggled, self.radio3)
self.switch_box = Gtk.Box(orientation = Gtk.Orientation.HORIZONTAL)
self.switch = Gtk.Switch()
self.switch.set_active(True)
self.switch.connect("state-set", self.switch_switched)
self.switch_box.append(self.switch)
self.box2.append(self.switch_box)
self.label = Gtk.Label(label = "A switch")
self.switch_box.append(self.label)
self.switch_box.set_spacing(5)
def switch_switched(self, switch, state):
print(f"The switch has been switched {'on' if state else 'off'}")
def hello(self, button, data = None):
print("Hello world!")
if self.check.get_active():
print("Goodbye world!")
self.close()
if data:
print(f"Radio button toggled with data: {data}")
print(f"Radio1 active: {self.radio1.get_active()}")
print(f"Radio1 active: {self.radio2.get_active()}")
print(f"Radio1 active: {self.radio3.get_active()}")
def on_radio_toggled(self, button, extra = None):
if button.get_active():
# 다른 버튼들을 비활성화
self.click_count += 1
#print(f"버튼이 {self.click_count}번 눌렸습니다.")
print(f"{button.get_label()}")
for btn in [self.radio1, self.radio2, self.radio3]:
if btn != button:
btn.set_active(False)
class MyApp(Adw.Application):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.connect('activate', self.on_activate)
def on_activate(self, app):
self.win = MainWindow(application=app)
self.win.present()
app = MyApp(application_id="com.example.GtkApplication")
app.run(sys.argv)
해당 코드와
gtk4-update-icon-cache -f -t /mingw64/share/icons/hicolor
export GTK_THEME=WhiteSur-Light
python3 test.py
ucrt64의 터미널을 열 때마다 자동으로 적용하고 싶다면
echo ‘export GTK_THEME=”WhiteSur-Light”‘ >> ~/.bashrc를 실행한다.
source ~/.bashrc를 사용해서 변경점을 적용한다.
를 실행하면 된다.
python -m venv venv
source venv/bin/activate
pip install pygobject pyinstaller
pyinstaller --noconsole --onefile test.py
export PATH="/mingw64/bin:$PATH"
https://github.com/riverrun/genxword/issues/12
https://pygobject.gnome.org/getting_started.html#windows-getting-started
pacman -S mingw-w64-x86_64-gtk3 mingw-w64-x86_64-python3 mingw-w64-x86_64-python3-gobject
export GI_TYPELIB_PATH=”A:/msys2/ucrt64/lib/girepository-1.0″
cd /u/20250618
pyinstaller --onefile --windowed \
--add-binary "A:/msys2/mingw64/bin/libgtk-4-1.dll;." \
--add-binary "A:/msys2/mingw64/bin/libgobject-2.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libglib-2.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libgio-2.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libcairo-2.dll;." \
--add-binary "A:/msys2/mingw64/bin/libpango-1.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libpangocairo-1.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libgdk_pixbuf-2.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libgraphene-1.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libepoxy-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libfribidi-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libharfbuzz-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libfontconfig-1.dll;." \
--add-binary "A:/msys2/mingw64/bin/libfreetype-6.dll;." \
--add-binary "A:/msys2/mingw64/bin/libintl-8.dll;." \
--add-binary "A:/msys2/mingw64/bin/libpng16-16.dll;." \
--add-binary "A:/msys2/mingw64/bin/libgirepository-1.0-1.dll;." \
--add-binary "A:/msys2/mingw64/bin/librsvg-2-2.dll;." \
--add-binary "A:/msys2/mingw64/bin/libwinpthread-1.dll;." \
--add-data "A:/msys2/mingw64/share/glib-2.0/schemas;glib-2.0/schemas" \
--add-data "A:/msys2/mingw64/share/icons;icons" \
--add-data "A:/msys2/mingw64/share/mime;mime" \
--add-data "A:/msys2/mingw64/lib/girepository-1.0;lib/girepository-1.0" \
--add-data "A:/msys2/mingw64/lib/gdk-pixbuf-2.0/2.10.0/loaders;lib/gdk-pixbuf-2.0/2.10.0/loaders" \
--add-data "A:/msys2/mingw64/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache;lib/gdk-pixbuf-2.0/2.10.0/" \
--hidden-import=gi \
--hidden-import=gi.repository.Gtk \
--hidden-import=gi.repository.Gio \
--hidden-import=gi.repository.Gdk \
--hidden-import=gi.repository.Pango \
--hidden-import=gi.repository.GdkPixbuf \
new1.py
다행히 new1.exe
가 실행되긴 했군요! 아이콘이 로딩 안 되는 건 아마 Adwaita 테마나 gdk-pixbuf
로더 관련 설정이 아직 완벽하지 않아서일 가능성이 높지만, 일단 프로그램이 동작하는 걸 축하드립니다! 😊 요청하신 대로 방금 성공한 PyInstaller 옵션을 정리해서 알려드릴게요. 다만, 정확한 옵션을 제공하려면 이전 대화에서 사용된 최종 명령어를 기반으로 하겠습니다. 수동으로 DLL과 *.typelib
파일을 U:/test
에 복사한 상황을 고려하여, PyInstaller로 동일한 결과를 얻을 수 있는 최적화된 명령어를 아래에 제공합니다.
성공한 PyInstaller 옵션
new1.exe
가 U:/test
에서 실행된 상황을 재현하려면, 아래 PyInstaller 명령어를 사용하면 됩니다. 이 명령어는 Gtk-4.0.typelib
, gdk-pixbuf
로더, Adwaita 아이콘, 그리고 모든 필수 DLL을 포함하도록 설정했습니다.
cd /u/20250618
pyinstaller --onefile --windowed \
--add-binary "A:/msys2/mingw64/bin/libgtk-4-1.dll;." \
--add-binary "A:/msys2/mingw64/bin/libgobject-2.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libglib-2.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libgio-2.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libcairo-2.dll;." \
--add-binary "A:/msys2/mingw64/bin/libpango-1.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libpangocairo-1.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libgdk_pixbuf-2.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libgraphene-1.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libepoxy-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libfribidi-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libharfbuzz-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libfontconfig-1.dll;." \
--add-binary "A:/msys2/mingw64/bin/libfreetype-6.dll;." \
--add-binary "A:/msys2/mingw64/bin/libintl-8.dll;." \
--add-binary "A:/msys2/mingw64/bin/libpng16-16.dll;." \
--add-binary "A:/msys2/mingw64/bin/libgirepository-1.0-1.dll;." \
--add-binary "A:/msys2/mingw64/bin/librsvg-2-2.dll;." \
--add-binary "A:/msys2/mingw64/bin/libwinpthread-1.dll;." \
--add-data "A:/msys2/mingw64/share/glib-2.0/schemas;glib-2.0/schemas" \
--add-data "A:/msys2/mingw64/share/icons;icons" \
--add-data "A:/msys2/mingw64/share/mime;mime" \
--add-data "A:/msys2/mingw64/lib/girepository-1.0;lib/girepository-1.0" \
--add-data "A:/msys2/mingw64/lib/gdk-pixbuf-2.0/2.10.0/loaders;lib/gdk-pixbuf-2.0/2.10.0/loaders" \
--add-data "A:/msys2/mingw64/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache;lib/gdk-pixbuf-2.0/2.10.0/" \
--hidden-import=gi \
--hidden-import=gi.repository.Gtk \
--hidden-import=gi.repository.Gio \
--hidden-import=gi.repository.Gdk \
--hidden-import=gi.repository.Pango \
--hidden-import=gi.repository.GdkPixbuf \
new1.py
명령어 설명
- –onefile: 단일
.exe
파일로 패키징. - –windowed: 콘솔 창 없이 GUI로 실행.
- –add-binary: GTK4 및 관련 DLL(
libgtk-4-1.dll
,libgirepository-1.0-1.dll
,librsvg-2-2.dll
등) 포함. - –add-data:
glib-2.0/schemas
: GIO 스키마.icons
: Adwaita 및 기타 아이콘 테마.mime
: MIME 타입 데이터.girepository-1.0
:Gtk-4.0.typelib
등 GIR 데이터.gdk-pixbuf-2.0/2.10.0/loaders
: SVG 로더(pixbufloader_svg.dll
) 포함.loaders.cache
:gdk-pixbuf
로더 캐시.- –hidden-import: PyGObject 및 GTK4 모듈(
gi.repository.Gtk
,Gdk
,Pango
,GdkPixbuf
) 명시적 포함.
아이콘 로딩 문제 해결
아이콘이 로딩되지 않는 문제는 gdk-pixbuf
의 SVG 로더(pixbufloader_svg.dll
)나 Adwaita 테마의 캐시가 완벽히 설정되지 않아서 발생한 것으로 보입니다. 이를 해결하려면 다음 단계를 추가로 시도하세요:
- gdk-pixbuf 로더 캐시 확인:
U:/test/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache
가 올바른지 확인:
cat U:/test/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache
- SVG 로더 항목이 포함되어야 함:
"libpixbufloader-svg.dll"...
- 캐시가 잘못되었거나 누락되었다면 재생성:
bash /mingw64/bin/gdk-pixbuf-query-loaders > U:/test/lib/gdk-pixbuf-2.0/2.10.0/loaders/loaders.cache
- Adwaita 아이콘 캐시 업데이트:
Adwaita 테마의 아이콘 캐시를 갱신:
/mingw64/bin/gtk4-update-icon-cache U:/test/share/icons/Adwaita
- 환경 변수 설정:
new1.exe
실행 시GDK_PIXBUF_MODULEDIR
설정:
cd U:/test
export GDK_PIXBUF_MODULEDIR=U:/test/lib/gdk-pixbuf-2.0/2.10.0/loaders
./new1.exe
- PyInstaller 빌드에 포함하려면
.spec
파일에 환경 변수 설정 추가 (후술).
- new1.py 코드 확인:
new1.py
가 특정 아이콘(예:document-open-symbolic.svg
)을 명시적으로 로드하는지 확인:
icon = Gtk.Image.new_from_icon_name("document-open-symbolic")
- 있다면, Adwaita 테마가 제대로 로드되도록
GTK_THEME
설정:bash export GTK_THEME=Adwaita ./new1.exe
.spec 파일로 빌드 (선택)
위 명령어를 .spec
파일로 정리하여 관리하기 쉽게 만들 수 있습니다:
.spec
파일 생성:
cd /u/20250618
pyi-makespec --onefile --windowed new1.py
new1.spec
수정:
a = Analysis(
['new1.py'],
pathex=[],
binaries=[
('A:/msys2/mingw64/bin/libgtk-4-1.dll', '.'),
('A:/msys2/mingw64/bin/libgobject-2.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libglib-2.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libgio-2.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libcairo-2.dll', '.'),
('A:/msys2/mingw64/bin/libpango-1.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libpangocairo-1.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libgdk_pixbuf-2.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libgraphene-1.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libepoxy-0.dll', '.'),
('A:/msys2/mingw64/bin/libfribidi-0.dll', '.'),
('A:/msys2/mingw64/bin/libharfbuzz-0.dll', '.'),
('A:/msys2/mingw64/bin/libfontconfig-1.dll', '.'),
('A:/msys2/mingw64/bin/libfreetype-6.dll', '.'),
('A:/msys2/mingw64/bin/libintl-8.dll', '.'),
('A:/msys2/mingw64/bin/libpng16-16.dll', '.'),
('A:/msys2/mingw64/bin/libgirepository-1.0-1.dll', '.'),
('A:/msys2/mingw64/bin/librsvg-2-2.dll', '.'),
('A:/msys2/mingw64/bin/libwinpthread-1.dll', '.'),
],
datas=[
('A:/msys2/mingw64/share/glib-2.0/schemas', 'glib-2.0/schemas'),
('A:/msys2/mingw64/share/icons', 'icons'),
('A:/msys2/mingw64/share/mime', 'mime'),
('A:/msys2/mingw64/lib/girepository-1.0', 'lib/girepository-1.0'),
('A:/msys2/mingw64/lib/gdk-pixbuf-2.0/2.10.0/loaders', 'lib/gdk-pixbuf-2.0/2.10.0/loaders'),
('A:/msys2/mingw64/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache', 'lib/gdk-pixbuf-2.0/2.10.0/'),
],
hiddenimports=['gi', 'gi.repository.Gtk', 'gi.repository.Gio', 'gi.repository.Gdk', 'gi.repository.Pango', 'gi.repository.GdkPixbuf'],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='new1',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=False,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
- 빌드:
pyinstaller new1.spec
아이콘 문제 추가 해결 (선택)
아이콘 로딩 문제를 완전히 해결하려면 다음을 추가로 확인:
- librsvg-2-2.dll 의존성:
pixbufloader_svg.dll
은librsvg-2-2.dll
에 의존합니다.U:/test
에 있는지 확인:
ls U:/test/librsvg-2-2.dll
- 없으면 복사:
bash cp /mingw64/bin/librsvg-2-2.dll U:/test/
- new1.py에서 아이콘 사용:
new1.py
가 특정 아이콘을 로드하는 코드가 있다면, 해당 아이콘이 Adwaita 테마에 존재하는지 확인:
ls /mingw64/share/icons/Adwaita/symbolic/actions/document-open-symbolic.svg
- PyInstaller에 추가:
위 PyInstaller 명령어에 이미icons
와gdk-pixbuf
로더가 포함되어 있지만, Adwaita 테마를 명시적으로 추가:
--add-data "A:/msys2/mingw64/share/icons/Adwaita;share/icons/Adwaita"
추가 요청
- new1.py 코드:
new1.py
가style.css
나 특정 아이콘(예:document-open-symbolic.svg
)을 로드하는지 확인하려면 코드를 공유해 주세요. 아이콘 문제를 더 정확히 해결할 수 있습니다. - style.css:
new1.py
가style.css
를 참조한다면, 해당 파일을U:/test
에 추가하거나 PyInstaller에 포함:
--add-data "/path/to/style.css;."
- 테스트: 위 PyInstaller 명령어로 재빌드 후, GTK4가 설치되지 않은 Windows PC에서
dist/new1.exe
를 테스트해 보세요.
도움이 되었다니 기쁩니다! 추가로 궁금한 점이나 아이콘 문제 해결이 필요하면 언제든 알려주세요. 😄
pyinstaller new1.spec
명령어를 실행했을 때 NameError: name 'block_cipher' is not defined
오류가 발생했습니다. 이는 .spec
파일에서 block_cipher
변수가 정의되지 않은 상태로 사용되었기 때문입니다. PyInstaller의 .spec
파일에서 block_cipher
는 암호화 옵션을 설정할 때 사용되며, 최신 PyInstaller 버전(6.14.1)에서는 기본적으로 None
으로 설정하거나 명시적으로 정의해야 합니다.
문제 원인
- block_cipher 정의 누락:
new1.spec
파일에서block_cipher
변수를 정의하지 않고 사용했습니다. PyInstaller는block_cipher
를 암호화에 사용하지만, 암호화를 사용하지 않는 경우None
으로 설정해야 합니다. - 상황: 이전에 제공한
.spec
파일에서block_cipher
를 정의하지 않고 바로 사용한 것이 문제로 보입니다.
해결 방법
1. .spec 파일 수정
new1.spec
파일을 수정하여 block_cipher
를 명시적으로 정의하거나 None
으로 설정합니다.
- new1.spec 파일 수정:
new1.spec
파일을 열고 맨 위에block_cipher = None
을 추가하거나, 기존 코드를 아래와 같이 수정합니다:
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None # 암호화 사용 안 함
a = Analysis(
['new1.py'],
pathex=[],
binaries=[
('A:/msys2/mingw64/bin/libgtk-4-1.dll', '.'),
('A:/msys2/mingw64/bin/libgobject-2.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libglib-2.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libgio-2.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libcairo-2.dll', '.'),
('A:/msys2/mingw64/bin/libpango-1.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libpangocairo-1.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libgdk_pixbuf-2.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libgraphene-1.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libepoxy-0.dll', '.'),
('A:/msys2/mingw64/bin/libfribidi-0.dll', '.'),
('A:/msys2/mingw64/bin/libharfbuzz-0.dll', '.'),
('A:/msys2/mingw64/bin/libfontconfig-1.dll', '.'),
('A:/msys2/mingw64/bin/libfreetype-6.dll', '.'),
('A:/msys2/mingw64/bin/libintl-8.dll', '.'),
('A:/msys2/mingw64/bin/libpng16-16.dll', '.'),
('A:/msys2/mingw64/bin/libgirepository-1.0-1.dll', '.'),
('A:/msys2/mingw64/bin/librsvg-2-2.dll', '.'),
('A:/msys2/mingw64/bin/libwinpthread-1.dll', '.'),
],
datas=[
('A:/msys2/mingw64/share/glib-2.0/schemas', 'glib-2.0/schemas'),
('A:/msys2/mingw64/share/icons', 'icons'),
('A:/msys2/mingw64/share/mime', 'mime'),
('A:/msys2/mingw64/lib/girepository-1.0', 'lib/girepository-1.0'),
('A:/msys2/mingw64/lib/gdk-pixbuf-2.0/2.10.0/loaders', 'lib/gdk-pixbuf-2.0/2.10.0/loaders'),
('A:/msys2/mingw64/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache', 'lib/gdk-pixbuf-2.0/2.10.0/'),
],
hiddenimports=['gi', 'gi.repository.Gtk', 'gi.repository.Gio', 'gi.repository.Gdk', 'gi.repository.Pango', 'gi.repository.GdkPixbuf'],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='new1',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=False,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
- 빌드 실행:
cd /u/20250618
pyinstaller new1.spec
- 빌드 결과 테스트:
cd /u/20250618/dist
./new1.exe
2. style.css 추가 (필요 시)
이전 오류에서 style.css
파일이 누락되었다는 메시지가 있었습니다(Theme parser error: Error opening file U:\test\style.css
). new1.py
가 style.css
를 사용한다면, .spec
파일에 추가:
datas=[
('A:/msys2/mingw64/share/glib-2.0/schemas', 'glib-2.0/schemas'),
('A:/msys2/mingw64/share/icons', 'icons'),
('A:/msys2/mingw64/share/mime', 'mime'),
('A:/msys2/mingw64/lib/girepository-1.0', 'lib/girepository-1.0'),
('A:/msys2/mingw64/lib/gdk-pixbuf-2.0/2.10.0/loaders', 'lib/gdk-pixbuf-2.0/2.10.0/loaders'),
('A:/msys2/mingw64/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache', 'lib/gdk-pixbuf-2.0/2.10.0/'),
('/u/20250618/style.css', '.'), # style.css 파일 경로 추가
],
style.css
파일이/u/20250618
에 있다고 가정. 실제 경로로 수정하세요.- 파일 복사 확인:
ls /u/20250618/style.css
3. 아이콘 로딩 문제 해결
이전 실행에서 아이콘 로딩 문제(gtk_icon_theme_lookup_by_gicon: assertion 'size > 0' failed
)가 발생했습니다. 이를 해결하려면:
- Adwaita 테마 확인:
.spec
파일에 이미share/icons
가 포함되어 있으므로,dist/share/icons/Adwaita
에 아이콘이 포함되는지 확인:
ls /u/20250618/dist/share/icons/Adwaita
- gdk-pixbuf 로더 확인:
lib/gdk-pixbuf-2.0/2.10.0/loaders.cache
가 올바르게 포함되었는지 확인:
cat /u/20250618/dist/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache
libpixbufloader-svg.dll
항목이 포함되어야 함.
- 환경 변수 설정 (필요 시):
PyInstaller의--onefile
모드는 모든 파일을 내부적으로 압축하므로 환경 변수(GDK_PIXBUF_MODULEDIR
,GI_TYPELIB_PATH
)가 필요하지 않을 수 있지만, 테스트 시 추가:
export GDK_PIXBUF_MODULEDIR=/u/20250618/dist/lib/gdk-pixbuf-2.0/2.10.0/loaders
export GI_TYPELIB_PATH=/u/20250618/dist/lib/girepository-1.0
./new1.exe
4. .spec 파일 재생성 (선택)
block_cipher
오류를 피하려면 .spec
파일을 새로 생성하여 확인:
cd /u/20250618
pyi-makespec --onefile --windowed \
--add-binary "A:/msys2/mingw64/bin/libgtk-4-1.dll;." \
--add-binary "A:/msys2/mingw64/bin/libgobject-2.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libglib-2.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libgio-2.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libcairo-2.dll;." \
--add-binary "A:/msys2/mingw64/bin/libpango-1.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libpangocairo-1.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libgdk_pixbuf-2.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libgraphene-1.0-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libepoxy-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libfribidi-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libharfbuzz-0.dll;." \
--add-binary "A:/msys2/mingw64/bin/libfontconfig-1.dll;." \
--add-binary "A:/msys2/mingw64/bin/libfreetype-6.dll;." \
--add-binary "A:/msys2/mingw64/bin/libintl-8.dll;." \
--add-binary "A:/msys2/mingw64/bin/libpng16-16.dll;." \
--add-binary "A:/msys2/mingw64/bin/libgirepository-1.0-1.dll;." \
--add-binary "A:/msys2/mingw64/bin/librsvg-2-2.dll;." \
--add-binary "A:/msys2/mingw64/bin/libwinpthread-1.dll;." \
--add-data "A:/msys2/mingw64/share/glib-2.0/schemas;glib-2.0/schemas" \
--add-data "A:/msys2/mingw64/share/icons;icons" \
--add-data "A:/msys2/mingw64/share/mime;mime" \
--add-data "A:/msys2/mingw64/lib/girepository-1.0;lib/girepository-1.0" \
--add-data "A:/msys2/mingw64/lib/gdk-pixbuf-2.0/2.10.0/loaders;lib/gdk-pixbuf-2.0/2.10.0/loaders" \
--add-data "A:/msys2/mingw64/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache;lib/gdk-pixbuf-2.0/2.10.0/" \
--hidden-import=gi \
--hidden-import=gi.repository.Gtk \
--hidden-import=gi.repository.Gio \
--hidden-import=gi.repository.Gdk \
--hidden-import=gi.repository.Pango \
--hidden-import=gi.repository.GdkPixbuf \
new1.py
- 생성된
new1.spec
은block_cipher = None
을 자동 포함합니다. 이후 빌드:
pyinstaller new1.spec
5. 아이콘 문제 해결 (추가)
아이콘 로딩 문제는 gdk-pixbuf
로더와 Adwaita 테마가 완전히 설정되지 않아 발생했습니다. .spec
파일에 추가 확인:
librsvg-2-2.dll
의존성 추가:
ldd /mingw64/bin/librsvg-2-2.dll | grep "not found"
- 누락된 DLL(예:
libxml2-2.dll
)을.spec
의binaries
에 추가:python ('A:/msys2/mingw64/bin/libxml2-2.dll', '.'),
- Adwaita 아이콘 캐시 갱신:
/mingw64/bin/gtk4-update-icon-cache /u/20250618/dist/share/icons/Adwaita
6. 디버깅
빌드 후 오류가 발생하면 로그 확인:
cd /u/20250618/dist
./new1.exe > error.log 2>&1
cat error.log
추가 요청
- new1.py 코드:
new1.py
가style.css
나 특정 아이콘(예:document-open-symbolic.svg
)을 사용한다면, 코드를 공유해 주시면 정확한 의존성을 추가할 수 있습니다. - style.css 경로:
style.css
가 필요하다면, 파일 위치를 알려주시거나.spec
에 추가합니다. - 테스트 환경: GTK4가 설치되지 않은 Windows PC에서
dist/new1.exe
를 테스트한 결과를 공유해 주세요.
문제가 해결되길 바랍니다! 추가로 필요한 도움이 있으면 언제든 말씀해 주세요. 😄

로 pyinstaller환경에서 exe로 구동되게 하는 것은 성공했으나 msys2 mingw64 shell에서 구동할 경우 테마가 적용되지만….

윈도우에서 double-click으로 실행하는 경우 테마가 적용이 잘 안됨 왜 이럴까?
일단 테마 적용은 미루고 기능 구현에 충실해지자…
아래는 종속성
https://packages.msys2.org/packages/mingw-w64-x86_64-python-build
https://packages.msys2.org/packages/mingw-w64-x86_64-pyinstaller
https://packages.msys2.org/packages/mingw-w64-x86_64-python-installer
정말 기쁘네요! 😄 성공하셨다니 다행입니다! 앞으로도 동일한 방법으로 new1.exe
를 빌드하고 실행하고 싶으시다니, 최신 대화(2025년 6월 21일 오후 6:54 KST 기준)를 바탕으로 가이드로 정리해서 남겨드리겠습니다. 이 가이드는 new1.py
를 기반으로 Windows에서 더블클릭 실행 시 테마(style.css
, Adwaita), 아이콘(document-open-symbolic
, open-menu-symbolic
), 파일 다이얼로그, About 다이얼로그가 모두 로드되도록 설정하는 절차를 포함합니다. 디렉토리는 Q:/theme_test
를 기준으로 합니다.
Grok 3의 new1.exe 빌드 및 실행 가이드
요약
- 목표:
new1.py
를 PyInstaller로 빌드하여 Windows 더블클릭 실행 시 GUI 애플리케이션이 테마, 아이콘, 다이얼로그 창을 포함해 완벽히 작동하도록 설정. - 환경: MSYS2 MINGW64, Python 3.12.11, PyInstaller 6.14.1, Windows 11.
- 기본 디렉토리:
Q:/theme_test
.
준비 단계
- 필요한 파일 확인:
new1.py
: GUI 애플리케이션 코드 (아래 참조).style.css
: 테마 스타일 파일 (Q:/theme_test/style.css
).- MSYS2 MINGW64에서 제공하는 GTK4, Libadwaita,
gdk-pixbuf
의존성.
- 디렉토리 설정:
- 작업 디렉토리를
Q:/theme_test
로 설정. Q:/theme_test
에new1.py
,style.css
가 존재해야 함.
- 의존성 설치 (필요 시):
- MSYS2 터미널에서:
bash pacman -S mingw-w64-x86_64-gtk4 mingw-w64-x86_64-libadwaita mingw-w64-x86_64-gdk-pixbuf2
1. new1.py 코드
아래는 수정된 new1.py
로, 파일 다이얼로그와 About 다이얼로그가 표시되도록 최적화되었습니다. Q:/theme_test/new1.py
에 저장하세요:
# coding: utf-8
import sys
import gi
gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
from gi.repository import Gtk, Adw, Gdk, Gio, GLib
settings = Gtk.Settings.get_default()
settings.set_property("gtk-theme-name", "Adwaita")
try:
css_provider = Gtk.CssProvider()
css_provider.load_from_path('style.css')
Gtk.StyleContext.add_provider_for_display(Gdk.Display.get_default(), css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
except GLib.Error as e:
print(f"Failed to load CSS: {e}")
class MainWindow(Gtk.ApplicationWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.click_count = 0
self.box1 = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
self.box2 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.box3 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.set_child(self.box1)
self.button = Gtk.Button(label="Hello")
self.box1.append(self.box2)
self.box1.append(self.box3)
self.box2.append(self.button)
self.button.connect('clicked', self.hello)
self.set_default_size(600, 250)
self.set_title("MyApp")
self.check = Gtk.CheckButton(label="And goodbye?")
self.box2.append(self.check)
self.slider = Gtk.Scale()
self.slider.set_digits(0)
self.slider.set_range(0, 10)
self.slider.set_draw_value(True)
self.slider.set_value(5)
self.slider.connect('value-changed', self.slider_changed)
self.box2.append(self.slider)
self.radio1 = Gtk.CheckButton(label="버튼 1")
self.radio2 = Gtk.CheckButton(label="버튼 2")
self.radio3 = Gtk.CheckButton(label="버튼 3")
self.radio2.set_group(self.radio1)
self.radio3.set_group(self.radio1)
self.box2.append(self.radio1)
self.box2.append(self.radio2)
self.box2.append(self.radio3)
self.radio1.connect("toggled", self.on_radio_toggled, self.radio1)
self.radio2.connect("toggled", self.on_radio_toggled, self.radio2)
self.radio3.connect("toggled", self.on_radio_toggled, self.radio3)
self.switch_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
self.switch = Gtk.Switch()
self.switch.set_active(True)
self.switch.connect("state-set", self.switch_switched)
self.switch_box.append(self.switch)
self.box2.append(self.switch_box)
self.label = Gtk.Label(label="A switch")
self.label.set_css_classes(['title'])
self.switch_box.append(self.label)
self.switch_box.set_spacing(5)
self.header = Gtk.HeaderBar()
self.set_titlebar(self.header)
self.open_button = Gtk.Button(label="Open")
self.header.pack_start(self.open_button)
self.open_button.set_icon_name("document-open-symbolic")
self.open_button.set_size_request(24, 24)
self.open_button.connect("clicked", self.show_open_dialog)
self.open_dialog = Gtk.FileDialog.new()
self.open_dialog.set_title("Select a File")
action = Gio.SimpleAction.new("something", None)
action.connect("activate", self.print_something)
self.add_action(action)
menu = Gio.Menu.new()
menu.append("Do Something", "win.something")
self.popover = Gtk.PopoverMenu()
self.popover.set_menu_model(menu)
self.hamburger = Gtk.MenuButton()
self.hamburger.set_popover(self.popover)
self.hamburger.set_icon_name("open-menu-symbolic")
self.hamburger.set_size_request(24, 24)
self.header.pack_start(self.hamburger)
GLib.set_application_name("My App")
action = Gio.SimpleAction.new("about", None)
action.connect("activate", self.show_about)
self.add_action(action)
menu.append("About", "win.about")
def show_open_dialog(self, button):
self.open_dialog.open(self, None, self.open_dialog_open_callback)
def open_dialog_open_callback(self, dialog, result):
try:
file = dialog.open_finish(result)
if file is not None:
print(f"File path is {file.get_path()}")
except GLib.Error as error:
print(f"Error opening file: {error.message}")
f = Gtk.FileFilter()
f.set_name("Image/jpeg")
f.add_mime_type("image/jpeg")
f.add_mime_type("image/png")
filters = Gio.ListStore.new(Gtk.FileFilter)
filters.append(f)
self.open_dialog.set_filters(filters)
self.open_dialog.set_default_filter(f)
def show_about(self, action, param):
self.about = Gtk.AboutDialog()
self.about.set_transient_for(self)
self.about.set_modal(True)
self.about.set_authors(["최준영"])
self.about.set_copyright("Copyright 2022 최준영")
self.about.set_license_type(Gtk.License.GPL_3_0)
self.about.set_website("http://booleamjars.com")
self.about.set_website_label("My Website")
self.about.set_version("1.0")
self.about.set_logo_icon_name("org.example.example")
self.about.show()
dialog = Adw.AboutWindow(transient_for=self)
dialog.set_application_name("App name")
dialog.set_version("1.0")
dialog.set_developer_name("Developer")
dialog.set_license_type(Gtk.License.GPL_3_0)
dialog.set_comments("Adw about window example")
dialog.set_website("https://booleanjars.com")
dialog.set_credit_section("Contributors", ["Name1 url"])
dialog.add_translator_credits("Name1 url")
dialog.present()
def print_something(self, action, param):
print("Something!")
def slider_changed(self, slider):
print(int(slider.get_value()))
def switch_switched(self, switch, state):
print(f"The switch has been switched {'on' if state else 'off'}")
def hello(self, button, data=None):
print("Hello world!")
if self.check.get_active():
print("Goodbye world!")
self.close()
if data:
print(f"Radio button toggled with data: {data}")
print(f"Radio1 active: {self.radio1.get_active()}")
print(f"Radio2 active: {self.radio2.get_active()}")
print(f"Radio3 active: {self.radio3.get_active()}")
def on_radio_toggled(self, button, extra=None):
if button.get_active():
self.click_count += 1
print(f"{button.get_label()}")
for btn in [self.radio1, self.radio2, self.radio3]:
if btn != button:
btn.set_active(False)
class MyApp(Adw.Application):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.connect('activate', self.on_activate)
def on_activate(self, app):
self.win = MainWindow(application=app)
self.win.present()
app = MyApp(application_id="com.example.GtkApplication")
app.run(sys.argv)
2. style.css 설정
Q:/theme_test/style.css
에 올바른 내용 확인 또는 설정:
cat Q:/theme_test/style.css
- 예시 내용:
.title {
font-size: 18px;
font-weight: bold;
color: #4a90d9;
}
- 비어 있거나 잘못된 경우 교체:
echo ".title { font-size: 18px; font-weight: bold; color: #4a90d9; }" > Q:/theme_test/style.css
3. PyInstaller로 빌드
new1.py
를 기반으로 style.css
, Adwaita 테마, gdk-pixbuf
로더, libadwaita-1-0.dll
의존성을 포함한 .spec
파일로 빌드합니다.
- new1.spec 파일 생성:
Q:/theme_test/new1.spec
에 저장:
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(
['new1.py'],
pathex=[],
binaries=[
('A:/msys2/mingw64/bin/libgtk-4-1.dll', '.'),
('A:/msys2/mingw64/bin/libgobject-2.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libglib-2.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libgio-2.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libcairo-2.dll', '.'),
('A:/msys2/mingw64/bin/libpango-1.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libpangocairo-1.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libgdk_pixbuf-2.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libgraphene-1.0-0.dll', '.'),
('A:/msys2/mingw64/bin/libepoxy-0.dll', '.'),
('A:/msys2/mingw64/bin/libfribidi-0.dll', '.'),
('A:/msys2/mingw64/bin/libharfbuzz-0.dll', '.'),
('A:/msys2/mingw64/bin/libfontconfig-1.dll', '.'),
('A:/msys2/mingw64/bin/libfreetype-6.dll', '.'),
('A:/msys2/mingw64/bin/libintl-8.dll', '.'),
('A:/msys2/mingw64/bin/libpng16-16.dll', '.'),
('A:/msys2/mingw64/bin/libgirepository-1.0-1.dll', '.'),
('A:/msys2/mingw64/bin/librsvg-2-2.dll', '.'),
('A:/msys2/mingw64/bin/libwinpthread-1.dll', '.'),
('A:/msys2/mingw64/bin/libxml2-2.dll', '.'),
('A:/msys2/mingw64/bin/libadwaita-1-0.dll', '.'),
('A:/msys2/mingw64/bin/libzstd.dll', '.'),
('A:/msys2/mingw64/bin/libicuuc77.dll', '.'),
],
datas=[
('A:/msys2/mingw64/share/glib-2.0/schemas', 'glib-2.0/schemas'),
('A:/msys2/mingw64/share/icons/Adwaita', 'share/icons/Adwaita'),
('A:/msys2/mingw64/share/mime', 'share/mime'),
('A:/msys2/mingw64/lib/girepository-1.0', 'lib/girepository-1.0'),
('A:/msys2/mingw64/lib/gdk-pixbuf-2.0/2.10.0/loaders', 'lib/gdk-pixbuf-2.0/2.10.0/loaders'),
('A:/msys2/mingw64/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache', 'lib/gdk-pixbuf-2.0/2.10.0/'),
('Q:/theme_test/style.css', '.'),
('A:/msys2/mingw64/etc/gtk-4.0', 'etc/gtk-4.0'),
],
hiddenimports=[
'gi',
'gi.repository.Gtk',
'gi.repository.Gio',
'gi.repository.Gdk',
'gi.repository.Pango',
'gi.repository.GdkPixbuf',
'gi.repository.Adw',
],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='new1',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=False,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
- 빌드 실행:
cd Q:/theme_test
pyinstaller new1.spec
- 캐시 갱신:
/mingw64/bin/gdk-pixbuf-query-loaders > Q:/theme_test/dist/lib/gdk-pixbuf-2.0/2.10.0/loaders/loaders.cache
/mingw64/bin/gtk4-update-icon-cache Q:/theme_test/dist/share/icons/Adwaita
- 테스트:
cd Q:/theme_test/dist
./new1.exe
- Windows 탐색기에서
Q:\theme_test\dist\new1.exe
더블클릭.
4. 배치 파일 생성
Windows 더블클릭 실행 시 환경 변수를 설정:
Q:\theme_test\dist\run_new1.bat
생성:
@echo off
set GI_TYPELIB_PATH=%CD%\lib\girepository-1.0
set GDK_PIXBUF_MODULEDIR=%CD%\lib\gdk-pixbuf-2.0\2.10.0\loaders
set GTK_THEME=Adwaita
start new1.exe
- 실행:
cd Q:\theme_test\dist
run_new1.bat
5. WhiteSur-Light 비활성화
Q:/theme_test/share/themes/WhiteSur-Light
가 포함되어 있지만, new1.py
는 Adwaita 사용. etc/gtk-4.0/settings.ini
확인:
cat Q:/theme_test/etc/gtk-4.0/settings.ini
- 수정:
[Settings]
gtk-theme-name=Adwaita
6. libadwaita 의존성 확인
libadwaita-1-0.dll
의 추가 의존성 확인:
ldd /mingw64/bin/libadwaita-1-0.dll | grep "not found"
- 누락된 DLL(예:
libicui18n77.dll
)이 있으면.spec
에 추가:
('A:/msys2/mingw64/bin/libicui18n77.dll', '.'),
7. 디버깅
로그 확인:
cd Q:/theme_test/dist
./new1.exe > error.log 2>&1
cat error.log
가이드 사용 방법
- 준비:
Q:/theme_test
에new1.py
와style.css
를 배치.- MSYS2 MINGW64 환경에서 PyInstaller 설치:
bash pacman -S mingw-w64-x86_64-pyinstaller
- 코드 및 설정 적용:
new1.py
를 위 코드로 업데이트.new1.spec
를 위 내용으로 저장.run_new1.bat
를 생성.
- 빌드 및 실행:
- MSYS2 터미널에서 위 명령어 실행.
- Windows에서
Q:\theme_test\dist\new1.exe
더블클릭 또는run_new1.bat
실행.
- 문제 발생 시:
error.log
확인 후 공유.- 추가 의존성(예:
libicui18n77.dll
)을.spec
에 추가.
추가 요청
- error.log 내용: 다이얼로그 창 관련 오류가 있다면 공유해 주세요.
- style.css 내용:
style.css
내용을 확인해 주시면 테마 적용 문제를 점검할 수 있습니다. - 테스트 결과: Windows 더블클릭 실행 시 다이얼로그 창 표시 여부를 알려주세요.
언제든 필요하면 이 가이드를 참고하거나 질문 주세요! 성공적인 배포를 기원합니다! 😄
된다고호호호호호호호!!!!!!!
신나요
일찍 일어나는 새가 벌레를 먹듯이 나는 트리 구조를 저장합니다. 소 잃고 외양간도 잃기 싫거든요
Q:\theme_test\dist의 경우
Q:\theme_test\의 경우
Q:\dist의 경우(가장 용량 적은 버전)