v2.11.2: 통계 차트 frozen 실제 수정(numpy _multiarray_tests) + 도전과제 라이트 가독성
- fix: frozen main.exe에서 numpy.core._multiarray_tests 누락으로 matplotlib import 실패 → 차트 폴백. spec에 hiddenimport 추가 + numpy.testing 제외 제거 (디버그 로그로 원인 확인) - fix: 도전과제 라이트 테마 헤더 숫자/배지/진행 텍스트/바 대비 개선 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e7e85dcf7b
commit
f5751460e3
10
CHANGELOG.md
10
CHANGELOG.md
@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
||||||
|
|
||||||
|
## [2.11.2] — 2026-06-04
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- **통계 차트가 빌드(main.exe)에서 안 뜨던 진짜 원인** — frozen 빌드에서 numpy C-확장
|
||||||
|
`numpy.core._multiarray_tests`가 누락(`numpy.testing` 제외의 영향)되어 matplotlib import가
|
||||||
|
`ModuleNotFoundError`로 실패 → "matplotlib 필요" 폴백. `main.spec`에 해당 모듈 hiddenimport
|
||||||
|
추가 + `numpy.testing` 제외 제거. (디버그 로그로 원인 확인: chart_widget이 실패 사유를 기록)
|
||||||
|
- **도전과제 라이트 테마 가독성** — 헤더 강조 숫자/등급 배지/진행 숫자/진행 바를 라이트에서
|
||||||
|
대비 높은 색으로 조정 (다크는 기존 비비드 색 유지).
|
||||||
|
|
||||||
## [2.11.1] — 2026-06-04
|
## [2.11.1] — 2026-06-04
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
@ -4,4 +4,4 @@
|
|||||||
릴리스 시 이 값을 올린 후 git tag → push.
|
릴리스 시 이 값을 올린 후 git tag → push.
|
||||||
CHANGELOG.md의 최상단 항목과 일치시킬 것.
|
CHANGELOG.md의 최상단 항목과 일치시킬 것.
|
||||||
"""
|
"""
|
||||||
__version__ = '2.11.1'
|
__version__ = '2.11.2'
|
||||||
|
|||||||
@ -36,11 +36,13 @@ a = Analysis(
|
|||||||
'matplotlib.backends.backend_qt5agg',
|
'matplotlib.backends.backend_qt5agg',
|
||||||
'PyQt5.QtSvg',
|
'PyQt5.QtSvg',
|
||||||
'PyQt5.sip', # matplotlib qt_compat가 sip 사용
|
'PyQt5.sip', # matplotlib qt_compat가 sip 사용
|
||||||
|
'numpy.core._multiarray_tests', # numpy import 체인이 참조 (frozen 차트 깨짐 방지)
|
||||||
],
|
],
|
||||||
hookspath=[],
|
hookspath=[],
|
||||||
hooksconfig={},
|
hooksconfig={},
|
||||||
runtime_hooks=[],
|
runtime_hooks=[],
|
||||||
excludes=['pandas', 'numpy.testing', 'PyQt5.QtWebEngineWidgets'],
|
# numpy.testing 제외 금지 — numpy.core._multiarray_tests 참조가 끊겨 matplotlib import 실패함
|
||||||
|
excludes=['pandas', 'PyQt5.QtWebEngineWidgets'],
|
||||||
noarchive=False,
|
noarchive=False,
|
||||||
optimize=0,
|
optimize=0,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -165,7 +165,13 @@ class AchievementsView(QDialog):
|
|||||||
num_row = QHBoxLayout()
|
num_row = QHBoxLayout()
|
||||||
num_row.setSpacing(24)
|
num_row.setSpacing(24)
|
||||||
|
|
||||||
big = QLabel(f"<span style='font-size: 32pt; font-weight: bold; color: #ffd24a;'>{stats['earned']}</span>"
|
# 헤더 강조 숫자색 — 다크는 비비드, 라이트는 동일 색조 진하게(가독성)
|
||||||
|
if _is_dark():
|
||||||
|
c_earned, c_secret, c_pct = '#ffd24a', '#ff90b8', '#4adef0'
|
||||||
|
else:
|
||||||
|
c_earned, c_secret, c_pct = '#C8950A', '#C2185B', '#0E7490'
|
||||||
|
|
||||||
|
big = QLabel(f"<span style='font-size: 32pt; font-weight: bold; color: {c_earned};'>{stats['earned']}</span>"
|
||||||
f"<span style='font-size: 18pt; color: {tc('text_dim')};'> / {stats['total']}</span>")
|
f"<span style='font-size: 18pt; color: {tc('text_dim')};'> / {stats['total']}</span>")
|
||||||
big.setTextFormat(Qt.RichText)
|
big.setTextFormat(Qt.RichText)
|
||||||
num_row.addWidget(big)
|
num_row.addWidget(big)
|
||||||
@ -178,7 +184,7 @@ class AchievementsView(QDialog):
|
|||||||
secret_lbl = QLabel(
|
secret_lbl = QLabel(
|
||||||
f"<div style='line-height: 1.3;'>"
|
f"<div style='line-height: 1.3;'>"
|
||||||
f"<span style='font-size: 9pt; color: {tc('text_dim')};'>🌑 시크릿</span><br>"
|
f"<span style='font-size: 9pt; color: {tc('text_dim')};'>🌑 시크릿</span><br>"
|
||||||
f"<span style='font-size: 18pt; font-weight: bold; color: #ff90b8;'>"
|
f"<span style='font-size: 18pt; font-weight: bold; color: {c_secret};'>"
|
||||||
f"{stats['secret_earned']}</span>"
|
f"{stats['secret_earned']}</span>"
|
||||||
f"<span style='font-size: 12pt; color: {tc('text_dim')};'> / {stats['secret_total']}</span>"
|
f"<span style='font-size: 12pt; color: {tc('text_dim')};'> / {stats['secret_total']}</span>"
|
||||||
f"</div>"
|
f"</div>"
|
||||||
@ -191,7 +197,7 @@ class AchievementsView(QDialog):
|
|||||||
pct_lbl = QLabel(
|
pct_lbl = QLabel(
|
||||||
f"<div style='text-align: right; line-height: 1.3;'>"
|
f"<div style='text-align: right; line-height: 1.3;'>"
|
||||||
f"<span style='font-size: 9pt; color: {tc('text_dim')};'>달성률</span><br>"
|
f"<span style='font-size: 9pt; color: {tc('text_dim')};'>달성률</span><br>"
|
||||||
f"<span style='font-size: 24pt; font-weight: bold; color: #4adef0;'>"
|
f"<span style='font-size: 24pt; font-weight: bold; color: {c_pct};'>"
|
||||||
f"{pct:.1f}%</span></div>"
|
f"{pct:.1f}%</span></div>"
|
||||||
)
|
)
|
||||||
pct_lbl.setTextFormat(Qt.RichText)
|
pct_lbl.setTextFormat(Qt.RichText)
|
||||||
@ -207,17 +213,17 @@ class AchievementsView(QDialog):
|
|||||||
bar.setTextVisible(False)
|
bar.setTextVisible(False)
|
||||||
bar.setMinimumHeight(8)
|
bar.setMinimumHeight(8)
|
||||||
bar.setMaximumHeight(8)
|
bar.setMaximumHeight(8)
|
||||||
bar.setStyleSheet("""
|
bar.setStyleSheet(f"""
|
||||||
QProgressBar {
|
QProgressBar {{
|
||||||
background: #1a1a26;
|
background: {tc('panel2')};
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}}
|
||||||
QProgressBar::chunk {
|
QProgressBar::chunk {{
|
||||||
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
|
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
|
||||||
stop:0 #4adef0, stop:0.5 #6b9eff, stop:1 #ff90b8);
|
stop:0 #4adef0, stop:0.5 #6b9eff, stop:1 #ff90b8);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}}
|
||||||
""")
|
""")
|
||||||
layout.addWidget(bar)
|
layout.addWidget(bar)
|
||||||
|
|
||||||
@ -343,8 +349,8 @@ class AchievementsView(QDialog):
|
|||||||
cat_label = QLabel(f" {theme['label']} {theme['name']} · {cat_text} ")
|
cat_label = QLabel(f" {theme['label']} {theme['name']} · {cat_text} ")
|
||||||
cat_label.setStyleSheet(
|
cat_label.setStyleSheet(
|
||||||
f"font-size: 8.5pt; "
|
f"font-size: 8.5pt; "
|
||||||
f"color: {theme['border_strong']}; "
|
f"color: {theme['border_strong'] if _is_dark() else tc('text_dim')}; "
|
||||||
f"background: rgba(255,255,255,0.05); "
|
f"background: {'rgba(255,255,255,0.05)' if _is_dark() else tc('panel2')}; "
|
||||||
f"border: 1px solid {theme['border']}; "
|
f"border: 1px solid {theme['border']}; "
|
||||||
f"border-radius: 8px; "
|
f"border-radius: 8px; "
|
||||||
f"padding: 1px 4px;"
|
f"padding: 1px 4px;"
|
||||||
@ -377,9 +383,9 @@ class AchievementsView(QDialog):
|
|||||||
if is_earned:
|
if is_earned:
|
||||||
earned = QLabel(f" ✓ {item['earned_date']} 달성 ")
|
earned = QLabel(f" ✓ {item['earned_date']} 달성 ")
|
||||||
earned.setStyleSheet(
|
earned.setStyleSheet(
|
||||||
f"color: {theme['border_strong']}; "
|
f"color: {theme['border_strong'] if _is_dark() else tc('text')}; "
|
||||||
f"font-weight: bold; font-size: 9.5pt; "
|
f"font-weight: bold; font-size: 9.5pt; "
|
||||||
f"background: rgba(255,255,255,0.08); "
|
f"background: {'rgba(255,255,255,0.08)' if _is_dark() else tc('panel2')}; "
|
||||||
f"border: 1px solid {theme['border']}; "
|
f"border: 1px solid {theme['border']}; "
|
||||||
f"border-radius: 6px; padding: 4px 8px;"
|
f"border-radius: 6px; padding: 4px 8px;"
|
||||||
)
|
)
|
||||||
@ -405,7 +411,7 @@ class AchievementsView(QDialog):
|
|||||||
pb.setMaximumHeight(10)
|
pb.setMaximumHeight(10)
|
||||||
pb.setStyleSheet(f"""
|
pb.setStyleSheet(f"""
|
||||||
QProgressBar {{
|
QProgressBar {{
|
||||||
background: rgba(0,0,0,0.4);
|
background: {'rgba(0,0,0,0.4)' if _is_dark() else tc('panel2')};
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}}
|
}}
|
||||||
@ -419,7 +425,7 @@ class AchievementsView(QDialog):
|
|||||||
|
|
||||||
num = QLabel(f"{progress} / {target}")
|
num = QLabel(f"{progress} / {target}")
|
||||||
num.setStyleSheet(
|
num.setStyleSheet(
|
||||||
f"color: {theme['border_strong']}; font-size: 9pt; "
|
f"color: {theme['border_strong'] if _is_dark() else tc('text_dim')}; font-size: 9pt; "
|
||||||
f"font-weight: bold; background: transparent; border: none;"
|
f"font-weight: bold; background: transparent; border: none;"
|
||||||
)
|
)
|
||||||
num.setMinimumWidth(60)
|
num.setMinimumWidth(60)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user