1
1
from typing import Dict , List , Callable
2
2
import tkinter as tk
3
3
import os
4
+ import sys
4
5
import json
5
6
from datetime import datetime , date
6
7
from constants import SCHEDULE_FILE , WEEKDAYS
10
11
11
12
class CourseScheduler :
12
13
"""课程表主应用类"""
13
- def __init__ (self ):
14
+ def __init__ (self , startup_action = None ):
14
15
"""初始化课程表应用"""
16
+ self .startup_action = startup_action
15
17
try :
16
18
logger .log_debug ("Initializing CourseScheduler application" )
17
19
# 先初始化配置
@@ -23,7 +25,9 @@ def __init__(self):
23
25
# 创建主窗口并应用配置
24
26
self .root = self ._create_root_window ()
25
27
logger .log_debug ("Main window created" )
28
+ # 应用窗口尺寸并强制更新布局
26
29
self .root .geometry (self .config_handler .geometry )
30
+ self .root .update_idletasks () # 立即应用窗口布局
27
31
28
32
# 初始化其他成员变量
29
33
self .schedule : Dict [str , List [Dict [str , str ]]] = {}
@@ -33,13 +37,18 @@ def __init__(self):
33
37
self .settings_window = None
34
38
self .about_window = None
35
39
self .main_menu = None
40
+ self .was_iconic = False # 初始化窗口状态跟踪属性
36
41
37
42
logger .log_debug ("Initializing schedule" )
38
43
self ._initialize_schedule ()
39
44
logger .log_debug ("Schedule initialized" )
40
45
logger .log_debug ("Initializing UI" )
41
46
self ._initialize_ui ()
42
47
logger .log_debug ("UI initialized" )
48
+
49
+ # 执行启动动作
50
+ if self .startup_action == 'open_settings' :
51
+ self .open_settings ()
43
52
except Exception as e :
44
53
logger .log_error (e )
45
54
raise
@@ -53,11 +62,16 @@ def _create_root_window(self) -> tk.Tk:
53
62
root .protocol ("WM_DELETE_WINDOW" , self .cleanup_resources ) # 退出时清理资源
54
63
55
64
# 设置透明图标和窗口类型
56
- # root.iconbitmap(default='res/icon.ico') # 设置默认图标
57
- root .attributes ('-toolwindow' , True ) # 设置为工具窗口样式
58
- root .attributes ('-topmost' , True ) # 保持窗口在最前
59
- root .after (100 , lambda : root .attributes ('-topmost' , False )) # 短暂置顶后取消
65
+ # 使用绝对路径并处理打包后的资源路径
66
+ base_path = getattr (sys , '_MEIPASS' , os .path .dirname (os .path .abspath (__file__ )))
67
+ icon_path = os .path .join (base_path , 'res' , 'icon.ico' )
68
+ root .iconbitmap (default = icon_path )
69
+ root .wm_iconbitmap (icon_path )
60
70
71
+ #窗口层级控制
72
+ root .attributes ('-toolwindow' , True ) # 设置为工具窗口样式
73
+ root .attributes ('-topmost' , True )
74
+ root .after (100 , lambda : root .attributes ('-topmost' , False ))
61
75
return root
62
76
63
77
def cleanup_resources (self ):
@@ -196,15 +210,57 @@ def _on_time_label_click(self, event):
196
210
"""处理时间标签点击事件"""
197
211
from tkinter import messagebox
198
212
from tools .fullscreen_time import FullscreenTimeWindow
213
+ from tools .weather_ui import WeatherUI
214
+ from tools .weather import WeatherAPI
199
215
200
- result = messagebox .askyesno (
201
- "全屏时间" ,
202
- "是否开启全屏时间?"
203
- )
204
- if result :
205
- if not hasattr (self , "fullscreen_time_window" ):
206
- self .fullscreen_time_window = FullscreenTimeWindow (self .root , self .config_handler )
207
- self .fullscreen_time_window .show ()
216
+ # 点击计数器
217
+ if not hasattr (self , '_click_count' ):
218
+ self ._click_count = 0
219
+ self ._click_count += 1
220
+
221
+ # 重置计数器定时器
222
+ if hasattr (self , '_click_timer' ):
223
+ self .root .after_cancel (self ._click_timer )
224
+ self ._click_timer = self .root .after (500 , self ._reset_click_count )
225
+
226
+ # 处理点击逻辑
227
+ if self ._click_count == 1 :
228
+ # 单次点击显示迷你天气
229
+ # 检查API密钥是否存在
230
+ if self .config_handler .heweather_api_key :
231
+ if not hasattr (self , "mini_weather" ):
232
+ from tools .weather_ui import MiniWeatherUI
233
+ main_geometry = self .root .geometry ()
234
+ self .mini_weather = MiniWeatherUI (
235
+ WeatherAPI (),
236
+ master = self .root
237
+ )
238
+ elif self ._click_count >= 3 :
239
+ # 三次点击显示全屏时间
240
+ self ._click_count = 0
241
+ if messagebox .askyesno ("确认" , "是否打开全屏大号时间?" ):
242
+ if not hasattr (self , "fullscreen_time_window" ):
243
+ from tools .fullscreen_time import FullscreenTimeWindow
244
+ self .fullscreen_time_window = FullscreenTimeWindow (self .root , self .config_handler )
245
+ self .fullscreen_time_window .show ()
246
+
247
+ def _reset_click_count (self ):
248
+ """重置点击计数器"""
249
+ self ._click_count = 0
250
+
251
+ def _show_click_tooltip (self , event ):
252
+ """显示点击提示气泡"""
253
+ # 创建气泡窗口
254
+ tooltip = tk .Toplevel (self .root )
255
+ tooltip .wm_overrideredirect (True )
256
+ tooltip .geometry (f"+{ event .x_root + 20 } +{ event .y_root + 20 } " )
257
+
258
+ # 气泡内容
259
+ label = tk .Label (tooltip , text = "待开发功能" , bg = "yellow" , fg = "black" , padx = 8 , pady = 4 )
260
+ label .pack ()
261
+
262
+ # 自动关闭定时器
263
+ tooltip .after (1500 , tooltip .destroy )
208
264
209
265
def _create_countdown_display (self ) -> None :
210
266
"""创建倒计时显示区域"""
@@ -263,6 +319,14 @@ def update_display(self) -> None:
263
319
self ._update_countdown_display (now )
264
320
self ._update_schedule_display (now )
265
321
self ._schedule_next_update ()
322
+
323
+ # 检测窗口状态变化
324
+ is_iconic = self .root .state () == 'iconic'
325
+ if self .was_iconic and not is_iconic :
326
+ # 窗口从最小化恢复时重新置顶
327
+ self .root .attributes ('-topmost' , True )
328
+ self .root .after (100 , lambda : self .root .attributes ('-topmost' , False ))
329
+ self .was_iconic = is_iconic
266
330
except Exception as e :
267
331
logger .log_error (e )
268
332
@@ -277,7 +341,11 @@ def _update_time_display(self, now: datetime) -> None:
277
341
def _update_countdown_display (self , now : datetime ) -> None :
278
342
"""更新倒计时显示"""
279
343
delta = (self .config_handler .countdown_date .date () - now .date ()).days
280
- self .countdown_label2 .config (text = str (delta ))
344
+ # 高考彩蛋:当倒计时名称是高考且天数<=100时显示红色
345
+ if self .config_handler .countdown_name == "高考" and delta <= 100 :
346
+ self .countdown_label2 .config (text = str (delta ), fg = "red" )
347
+ else :
348
+ self .countdown_label2 .config (text = str (delta ), fg = self .config_handler .font_color )
281
349
282
350
def _update_schedule_display (self , now : datetime ) -> None :
283
351
"""更新课程表显示"""
@@ -321,7 +389,7 @@ def _get_course_color(self, now: datetime, course: Dict[str, str]) -> str:
321
389
return "yellow" # 正在上的课程为黄色
322
390
elif current_time > end_time :
323
391
return "green" # 已上完的课程为绿色
324
- return "#ffcccc " # 未上过的课程为浅红色
392
+ return "red " # 未上过的课程为红色
325
393
326
394
def _update_existing_label (self , index : int , course : Dict [str , str ], color : str ) -> None :
327
395
"""更新现有课程标签"""
0 commit comments