时间范围选择组件:删除旧的年月日 Spinbox,统一使用日历弹窗选择日期;保留时分选择。 输入采集:开始日期+时分、结束预设或自定义日期+时分。
| 6 | |
| 7 | |
| 8 | class TimeRangeSelector(ttk.Frame): |
| 9 | """ |
| 10 | 时间范围选择组件:删除旧的年月日 Spinbox,统一使用日历弹窗选择日期;保留时分选择。 |
| 11 | |
| 12 | 输入采集:开始日期+时分、结束预设或自定义日期+时分。 |
| 13 | """ |
| 14 | |
| 15 | def __init__(self, master: tk.Misc): |
| 16 | super().__init__(master) |
| 17 | |
| 18 | now = datetime.now() |
| 19 | |
| 20 | ttk.Label(self, text="开始时间").grid(row=0, column=0, padx=5, pady=6, sticky="w") |
| 21 | self._start_y, self._start_m, self._start_d = now.year, now.month, now.day |
| 22 | self.start_date_str = tk.StringVar(value=f"{self._start_y}-{self._start_m:02d}-{self._start_d:02d}") |
| 23 | ttk.Label(self, textvariable=self.start_date_str, width=12).grid(row=0, column=1, padx=2) |
| 24 | s_pick = ttk.Button(self, text="选择日期") |
| 25 | s_pick.grid(row=0, column=3, padx=8) |
| 26 | |
| 27 | ttk.Label(self, text="结束时间").grid(row=1, column=0, padx=5, pady=6, sticky="w") |
| 28 | self.preset_var = tk.StringVar(value="35") |
| 29 | preset = ttk.Combobox(self, textvariable=self.preset_var, values=["7", "14", "35", "自定义"], width=6, state="readonly") |
| 30 | preset.grid(row=1, column=1, padx=2) |
| 31 | |
| 32 | self._end_y, self._end_m, self._end_d = now.year, now.month, now.day |
| 33 | self.end_date_str = tk.StringVar(value=f"{self._end_y}-{self._end_m:02d}-{self._end_d:02d}") |
| 34 | self.end_date_label = ttk.Label(self, textvariable=self.end_date_str, width=12) |
| 35 | self.end_date_label.grid(row=1, column=2, padx=2) |
| 36 | e_pick = ttk.Button(self, text="选择日期", state="disabled") |
| 37 | e_pick.grid(row=1, column=3, padx=8) |
| 38 | |
| 39 | def _toggle_end_fields(event=None): |
| 40 | v = self.preset_var.get() |
| 41 | st = "normal" if v == "自定义" else "disabled" |
| 42 | e_pick.config(state=("normal" if v == "自定义" else "disabled")) |
| 43 | |
| 44 | preset.bind("<<ComboboxSelected>>", _toggle_end_fields) |
| 45 | |
| 46 | def _open_calendar(target: str): |
| 47 | cal = CalendarPopup(self) |
| 48 | limit_max = date(3000, 12, 31) |
| 49 | if target == "start": |
| 50 | y, m, d = self._start_y, self._start_m, self._start_d |
| 51 | min_d = datetime.now().date() |
| 52 | max_d = limit_max |
| 53 | else: |
| 54 | y, m, d = self._end_y, self._end_m, self._end_d |
| 55 | min_d = date(self._start_y, self._start_m, self._start_d) |
| 56 | max_d = limit_max |
| 57 | cal.show(y, m, d, lambda yy, mm, dd: self._apply_date(target, yy, mm, dd), min_date=min_d, max_date=max_d) |
| 58 | |
| 59 | s_pick.config(command=lambda: _open_calendar("start")) |
| 60 | e_pick.config(command=lambda: _open_calendar("end")) |
| 61 | |
| 62 | def _apply_date(self, target: str, y: int, m: int, d: int): |
| 63 | if target == "start": |
| 64 | self._start_y, self._start_m, self._start_d = y, m, d |
| 65 | self.start_date_str.set(f"{y}-{m:02d}-{d:02d}") |