From 7efff7d62e2530af101bd23016b5e58cde5dc22f Mon Sep 17 00:00:00 2001 From: xiaji Date: Wed, 21 Jan 2026 18:21:56 +0800 Subject: [PATCH] =?UTF-8?q?Initial=20commit:=20=E8=BF=B0=E8=81=8C=E8=AE=A1?= =?UTF-8?q?=E6=97=B6=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 19 ++ Timer.ico | Bin 0 -> 4286 bytes countdown.py | 832 +++++++++++++++++++++++++++++++++++++++++++++++++++ 要求.txt | 18 ++ 4 files changed, 869 insertions(+) create mode 100644 .gitignore create mode 100644 Timer.ico create mode 100644 countdown.py create mode 100644 要求.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ff86efa --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +dist/ +*.spec + +# IDE +.idea/ +.vscode/ +*.swp +*.swo + +# OS +.DS_Store +Thumbs.db diff --git a/Timer.ico b/Timer.ico new file mode 100644 index 0000000000000000000000000000000000000000..e88fe317c2700c537ad7185ad9652fec9c791205 GIT binary patch literal 4286 zcmeHKzfTlF6keb(Hl7$IF~Z$mFww>ek=tnQt}!%PU_yf-26n+1?QASAx5OhF3*--w z7|az=DA-|1VRBNf%2^nj0}}1X@got#WykLu*krxz-tK}n#3k=`_Wk(Yn>TOX42sf( zKUG!utIVEMlr}|CE`q>PvLN#Lj6wGQIT{%lh+k^e+qLr~j{o(nOhsuPQMFz})m|A% zZADj8Hr|4?KVG4XI@JA}@fh)*>%g}3Wa<~*3wly}Fr2ue-RbD+BymjMo=oakv^i`H zoCkbPV2-<-8+`>~QpZqxn4?|f<@rH#(XS{iu%Ch7^^v%C!^`iuQJx}s$!J4cVi3zq zrxA~_8_864q@%mrPp_aa7YoL6(N9iWVi3zu$BQr5oB4~UZhFZbUcvY>L~_2p-ZBqd zzmWC7^+Mh(uD2K7L3pwrfElJ1xPMsZVQMXGEW{!vv4d<3H8qX7F9hjPj&*%T3ZqL* zVh8DB-&Bl*c0Wjua?GiS`tq$mHwH0@?dH{wWlu$4V?U{vd3{ImFMAZQ8}(}Ta>OW{ zwJ&6EO+C)^6$_a@&l;Eh)zqw4Y;$k7hhEQb7T?To%l;ty5_>g#cs1hUM*Pi^~mAlyTu-oNA>Ro=gdK`det`zd@l{=D9% zUOvSbsn3|HBkRF+|KwT1e!{vYaV*alc{ly@{z(k!oAU;?m(O~hi~+GSUrs$RhuoXk zU(?7(1$nK%e^)4@4t0r1TbXlUh4t;kBG-a>KutP4_gnVrfd4;e%UlNK+>PrVvrf1# z+`K4b+WOU66r7{1E8I^lBgA5h5Mxckj#bTCI+v;C^O+snOl$}-N!qeai?n8&rPXw< zcQt*jcTFTpTOwv{iAifil%TgZxnn;}ywB%57t^_xO00UUI@T21$u=iyxpc-hZPRi4 E8!eXhEC2ui literal 0 HcmV?d00001 diff --git a/countdown.py b/countdown.py new file mode 100644 index 0000000..cbedc6a --- /dev/null +++ b/countdown.py @@ -0,0 +1,832 @@ +""" +述职计时器 - 倒计时应用程序 +使用 PySide6 构建的美观倒计时器 +""" + +import sys +import json +from pathlib import Path +from PySide6.QtWidgets import ( + QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, + QPushButton, QLabel, QDialog, QSpinBox, QCheckBox, QSlider, QFormLayout, QGroupBox +) +from PySide6.QtCore import QTimer, Qt, QPropertyAnimation, QEasingCurve, Property +from PySide6.QtGui import QFont +from PySide6.QtMultimedia import QSoundEffect, QAudioOutput, QMediaPlayer +from PySide6.QtCore import QUrl + + +class ConfigDialog(QDialog): + """配置对话框""" + + def __init__(self, parent=None): + super().__init__(parent) + self.setWindowTitle("其它设置") + self.setModal(True) + self.resize(400, 300) + + layout = QFormLayout() + + # 自定义倒计时时间(秒) + self.custom_time_spin = QSpinBox() + self.custom_time_spin.setRange(1, 3600) + self.custom_time_spin.setValue(300) + self.custom_time_spin.setSuffix(" 秒") + layout.addRow("自定义倒计时:", self.custom_time_spin) + + # 提前告警时间(秒) + self.alert_time_spin = QSpinBox() + self.alert_time_spin.setRange(0, 600) + self.alert_time_spin.setValue(60) + self.alert_time_spin.setSuffix(" 秒") + layout.addRow("提前告警:", self.alert_time_spin) + + # 置顶选项 + self.topmost_checkbox = QCheckBox() + self.topmost_checkbox.setChecked(True) + layout.addRow("窗口置顶:", self.topmost_checkbox) + + # 透明度滑块 + self.opacity_slider = QSlider(Qt.Horizontal) + self.opacity_slider.setRange(10, 100) + self.opacity_slider.setValue(90) + self.opacity_slider.setTickPosition(QSlider.TicksBelow) + self.opacity_slider.setTickInterval(10) + self.opacity_label = QLabel("90%") + self.opacity_slider.valueChanged.connect( + lambda v: self.opacity_label.setText(f"{v}%") + ) + + opacity_layout = QHBoxLayout() + opacity_layout.addWidget(self.opacity_slider) + opacity_layout.addWidget(self.opacity_label) + layout.addRow("窗口透明度:", opacity_layout) + + # 测试告警按钮 + self.test_alert_button = QPushButton("测试告警声音") + self.test_alert_button.clicked.connect(self.test_alert_sound) + self.test_alert_button.setStyleSheet(""" + QPushButton { + background-color: #3498db; + color: white; + border: none; + padding: 8px 16px; + border-radius: 4px; + font-size: 14px; + } + QPushButton:hover { + background-color: #2980b9; + } + """) + layout.addRow("", self.test_alert_button) + + # 按钮 + button_layout = QHBoxLayout() + + self.ok_button = QPushButton("确定") + self.ok_button.clicked.connect(self.accept) + self.ok_button.setStyleSheet(""" + QPushButton { + background-color: #4CAF50; + color: white; + border: none; + padding: 8px 16px; + border-radius: 4px; + font-size: 14px; + } + QPushButton:hover { + background-color: #45a049; + } + """) + + self.cancel_button = QPushButton("取消") + self.cancel_button.clicked.connect(self.reject) + self.cancel_button.setStyleSheet(""" + QPushButton { + background-color: #f44336; + color: white; + border: none; + padding: 8px 16px; + border-radius: 4px; + font-size: 14px; + } + QPushButton:hover { + background-color: #da190b; + } + """) + + self.exit_button = QPushButton("退出") + self.exit_button.clicked.connect(self.exit_application) + self.exit_button.setStyleSheet(""" + QPushButton { + background-color: #95a5a6; + color: white; + border: none; + padding: 8px 16px; + border-radius: 4px; + font-size: 14px; + } + QPushButton:hover { + background-color: #7f8c8d; + } + """) + + button_layout.addWidget(self.ok_button) + button_layout.addWidget(self.cancel_button) + button_layout.addWidget(self.exit_button) + + layout.addRow(button_layout) + + self.setLayout(layout) + + # 样式 + self.setStyleSheet(""" + QDialog { + background-color: #f5f5f5; + } + QLabel { + font-size: 13px; + color: #333; + } + QSpinBox { + padding: 5px; + border: 1px solid #ddd; + border-radius: 4px; + font-size: 13px; + } + """) + + def test_alert_sound(self): + """测试告警声音""" + try: + QApplication.beep() + # 循环播放2次 + QTimer.singleShot(500, QApplication.beep) + QTimer.singleShot(1000, QApplication.beep) + except Exception as e: + print(f"播放测试告警音失败: {e}") + + def exit_application(self): + """退出应用程序""" + self.accept() # 关闭对话框 + # 退出整个应用程序 + QApplication.quit() + + +class CountdownTimer(QMainWindow): + """主倒计时器窗口""" + + def __init__(self): + super().__init__() + + # 配置 + self.config_file = Path.home() / ".countdown_timer_config.json" + self.load_config() + + # 状态 + self.remaining_seconds = 0 + self.total_seconds = 0 + self.is_running = False + self.alert_played = False + self.alert_loop_count = 0 + + # 定时器 + self.timer = QTimer() + self.timer.timeout.connect(self.update_timer) + + # 闪烁动画定时器 + self.blink_timer = QTimer() + self.blink_timer.timeout.connect(self.toggle_blink) + self.blink_state = True + + # 音频播放器(用于告警提示音) + self.media_player = None + + self.init_ui() + self.apply_config() + + # 鼠标位置跟踪(用于窗口移动) + self.drag_position = None + + # 状态管理 + self.current_state = "normal" # normal 或 mini + self.state_change_timer = None + + def mousePressEvent(self, event): + """鼠标按下事件 - 开始移动窗口""" + if event.button() == Qt.LeftButton: + self.drag_position = event.globalPosition().toPoint() - self.frameGeometry().topLeft() + event.accept() + + def mouseMoveEvent(self, event): + """鼠标移动事件 - 移动窗口""" + if self.drag_position is not None and event.buttons() == Qt.LeftButton: + self.move(event.globalPosition().toPoint() - self.drag_position) + event.accept() + + def mouseReleaseEvent(self, event): + """鼠标释放事件 - 停止移动窗口""" + if event.button() == Qt.LeftButton: + self.drag_position = None + event.accept() + + def load_config(self): + """加载配置""" + default_config = { + "alert_seconds": 60, + "topmost": True, + "opacity": 90, + "custom_seconds": 300 + } + + if self.config_file.exists(): + try: + with open(self.config_file, 'r', encoding='utf-8') as f: + self.config = json.load(f) + # 合并默认值 + for key, value in default_config.items(): + if key not in self.config: + self.config[key] = value + except: + self.config = default_config + else: + self.config = default_config + + def save_config(self): + """保存配置""" + try: + with open(self.config_file, 'w', encoding='utf-8') as f: + json.dump(self.config, f, ensure_ascii=False, indent=2) + except: + pass + + def apply_config(self): + """应用配置""" + # 透明度 + self.setWindowOpacity(self.config["opacity"] / 100.0) + + # 置顶 + if self.config["topmost"]: + self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint) + else: + self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint) + + self.show() + + # 保存初始窗口位置(等待窗口显示完成) + QTimer.singleShot(100, self.save_initial_position) + + def save_initial_position(self): + """保存初始窗口位置""" + self.initial_pos = self.pos() + + def init_ui(self): + """初始化UI""" + # 设置无边框窗口 + self.setWindowFlags(Qt.FramelessWindowHint) + # 设置最小窗口大小(初始状态) + self.setMinimumSize(250, 100) + # 设置初始窗口大小(倒计时模式) + self.resize(500, 300) + + # 中心部件 + central_widget = QWidget() + self.setCentralWidget(central_widget) + + main_layout = QVBoxLayout() + main_layout.setSpacing(20) + main_layout.setContentsMargins(30, 30, 30, 30) + + # 倒计时显示 + self.time_label = QLabel("00:00") + self.time_label.setAlignment(Qt.AlignCenter) + self.time_label.setStyleSheet(""" + QLabel { + font-size: 72px; + font-weight: bold; + color: #3498db; + font-family: 'Courier New', monospace; + background-color: #ecf0f1; + border-radius: 10px; + padding: 20px; + } + """) + main_layout.addWidget(self.time_label) + + # 完成提示标签(初始隐藏) + self.finish_label = QLabel("时间已到") + self.finish_label.setAlignment(Qt.AlignCenter) + self.finish_label.setStyleSheet(""" + QLabel { + font-size: 48px; + font-weight: bold; + color: #e74c3c; + background-color: #fee; + border-radius: 10px; + padding: 20px; + } + """) + self.finish_label.hide() + main_layout.addWidget(self.finish_label) + + # 创建可折叠的按钮区域 + self.button_group = QGroupBox() + self.button_group.setStyleSheet(""" + QGroupBox { + border: 2px solid #bdc3c7; + border-radius: 8px; + margin-top: 10px; + padding-top: 10px; + background-color: #f8f9fa; + } + QGroupBox::title { + subcontrol-origin: margin; + left: 10px; + padding: 0 5px 0 5px; + } + """) + + # 折叠/展开按钮 + self.collapse_button = QPushButton("▼") + self.collapse_button.setFixedSize(30, 30) + self.collapse_button.setStyleSheet(""" + QPushButton { + background-color: #3498db; + color: white; + border: none; + border-radius: 4px; + font-size: 12px; + font-weight: bold; + } + QPushButton:hover { + background-color: #2980b9; + } + """) + self.collapse_button.clicked.connect(self.toggle_button_group) + + # 按钮布局 + button_layout = QHBoxLayout() + button_layout.setSpacing(15) + + # 创建按钮 + self.btn_5min = self.create_button("5分钟", lambda: self.start_countdown(300)) + self.btn_6min = self.create_button("6分钟", lambda: self.start_countdown(360)) + self.btn_other = self.create_button("其它", self.open_config, "#95a5a6") + + button_layout.addWidget(self.btn_5min) + button_layout.addWidget(self.btn_6min) + button_layout.addWidget(self.btn_other) + + # 控制按钮 + control_layout = QHBoxLayout() + + self.btn_pause = self.create_button("暂停", self.pause_countdown, "#f39c12") + self.btn_reset = self.create_button("重置", self.reset_countdown, "#e74c3c") + + self.btn_pause.setEnabled(False) + self.btn_reset.setEnabled(False) + + control_layout.addWidget(self.btn_pause) + control_layout.addWidget(self.btn_reset) + + # 添加到按钮组 + group_layout = QVBoxLayout() + group_layout.addLayout(button_layout) + group_layout.addLayout(control_layout) + self.button_group.setLayout(group_layout) + + # 主布局添加折叠按钮和按钮组 + main_layout.addWidget(self.collapse_button) + main_layout.addWidget(self.button_group) + + # 默认折叠按钮区 + self.button_group.hide() + self.collapse_button.setText("▶") + + central_widget.setLayout(main_layout) + + # 窗口样式 + self.setStyleSheet(""" + QMainWindow { + background-color: #ffffff; + } + """) + + def create_button(self, text, callback, color="#3498db"): + """创建样式化按钮""" + button = QPushButton(text) + button.clicked.connect(callback) + button.setMinimumHeight(20) # 减小按钮高度 + button.setMinimumWidth(50) # 设置最小宽度 + button.setStyleSheet(f""" + QPushButton {{ + background-color: {color}; + color: white; + border: none; + border-radius: 4px; + font-size: 11px; + font-weight: bold; + padding: 2px 5px; + }} + QPushButton:hover {{ + background-color: {self.darken_color(color)}; + }} + QPushButton:pressed {{ + background-color: {self.darken_color(color, 0.3)}; + }} + QPushButton:disabled {{ + background-color: #bdc3c7; + }} + """) + return button + + def darken_color(self, hex_color, factor=0.15): + """使颜色变暗""" + hex_color = hex_color.lstrip('#') + r, g, b = tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4)) + r = int(r * (1 - factor)) + g = int(g * (1 - factor)) + b = int(b * (1 - factor)) + return f"#{r:02x}{g:02x}{b:02x}" + + def start_countdown(self, seconds): + """开始倒计时""" + self.remaining_seconds = seconds + self.total_seconds = seconds + self.is_running = True + self.alert_played = False + self.alert_loop_count = 0 + + # 折叠按钮区域 + self.button_group.hide() + self.collapse_button.setText("▶") + + # 设置2秒后切换到微缩状态的定时器 + if self.state_change_timer: + self.state_change_timer.stop() + self.state_change_timer = QTimer() + self.state_change_timer.timeout.connect(self.switch_to_mini_state) + self.state_change_timer.start(2000) # 2秒后切换 + + # 立即切换到微缩状态 + self.switch_to_mini_state() + + self.timer.start(1000) + self.update_display() + + # 隐藏完成标签,显示倒计时 + self.finish_label.hide() + self.time_label.show() + self.blink_timer.stop() + + # 更新按钮状态 + self.btn_pause.setEnabled(True) + self.btn_pause.setText("暂停") + self.btn_reset.setEnabled(True) + + def pause_countdown(self): + """暂停/继续倒计时""" + if self.is_running: + self.timer.stop() + self.is_running = False + self.btn_pause.setText("继续") + else: + self.timer.start(1000) + self.is_running = True + self.btn_pause.setText("暂停") + + def reset_countdown(self): + """重置倒计时""" + self.timer.stop() + self.blink_timer.stop() + self.is_running = False + self.remaining_seconds = 0 + self.alert_played = False + self.alert_loop_count = 0 + + # 恢复原始窗口大小 + self.resize(500, 300) + + # 恢复窗口置顶状态 + self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint) + self.show() + + self.time_label.setText("00:00") + self.time_label.show() + self.finish_label.hide() + + self.btn_pause.setEnabled(False) + self.btn_pause.setText("暂停") + self.btn_reset.setEnabled(False) + + # 停止音频 + if self.media_player: + self.media_player.stop() + + def switch_to_mini_state(self): + """切换到微缩状态""" + self.current_state = "mini" + + # 调整窗口大小为微缩模式(200x80像素,增加高度以容纳倒计时) + self.resize(200, 80) + + # 移动窗口位置到距离top 50px,距离右边200px + screen = QApplication.primaryScreen().geometry() + screen_width = screen.width() + screen_height = screen.height() + new_x = screen_width - 200 - 200 # 距离右边200px + new_y = 50 # 距离top 50px + self.move(new_x, new_y) + + # 隐藏按钮区域 + self.button_group.hide() + self.collapse_button.setText("▼") + + # 调整布局边距以适应微缩状态 + central_widget = self.centralWidget() + main_layout = central_widget.layout() + main_layout.setSpacing(5) + main_layout.setContentsMargins(10, 10, 10, 10) + + # 调整倒计时标签大小以适应微缩状态 + self.time_label.setStyleSheet(""" + QLabel { + font-size: 12px; + font-weight: bold; + color: #3498db; + font-family: 'Courier New', monospace; + background-color: #ecf0f1; + border-radius: 3px; + padding: 2px; + } + """) + + # 隐藏完成提示标签 + self.finish_label.hide() + + # 确保窗口在最前面 + self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint) + self.show() + + def switch_to_normal_state(self): + """切换到正常状态""" + self.current_state = "normal" + + # 取消2秒定时器(如果存在) + if self.state_change_timer and self.state_change_timer.isActive(): + self.state_change_timer.stop() + + # 恢复原始窗口大小 + self.resize(500, 300) + + # 恢复初始窗口位置 + if hasattr(self, 'initial_pos') and self.initial_pos.x() >= 0 and self.initial_pos.y() >= 0: + self.move(self.initial_pos) + + # 恢复窗口置顶状态 + self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint) + self.show() + + # 恢复布局边距 + central_widget = self.centralWidget() + main_layout = central_widget.layout() + main_layout.setSpacing(20) + main_layout.setContentsMargins(30, 30, 30, 30) + + # 恢复倒计时标签的正常样式 + self.time_label.setStyleSheet(""" + QLabel { + font-size: 72px; + font-weight: bold; + color: #3498db; + font-family: 'Courier New', monospace; + background-color: #ecf0f1; + border-radius: 10px; + padding: 20px; + } + """) + + # 如果按钮区域之前是展开的,重新展开 + if not self.button_group.isHidden(): + self.button_group.hide() + self.collapse_button.setText("▶") + + def update_timer(self): + """更新计时器""" + if self.remaining_seconds > 0: + self.remaining_seconds -= 1 + self.update_display() + + # 检查是否需要播放告警 + if (not self.alert_played and + self.remaining_seconds <= self.config["alert_seconds"] and + self.remaining_seconds > 0): + self.play_alert() + self.alert_played = True + else: + # 倒计时结束 + self.timer.stop() + self.is_running = False + self.show_finish() + + def update_display(self): + """更新显示""" + minutes = self.remaining_seconds // 60 + seconds = self.remaining_seconds % 60 + self.time_label.setText(f"{minutes:02d}:{seconds:02d}") + + # 根据剩余时间改变颜色 + if self.remaining_seconds <= 10: + self.time_label.setStyleSheet(""" + QLabel { + font-size: 72px; + font-weight: bold; + color: #e74c3c; + font-family: 'Courier New', monospace; + background-color: #fee; + border-radius: 10px; + padding: 20px; + } + """) + elif self.remaining_seconds <= self.config["alert_seconds"]: + self.time_label.setStyleSheet(""" + QLabel { + font-size: 72px; + font-weight: bold; + color: #f39c12; + font-family: 'Courier New', monospace; + background-color: #fef5e7; + border-radius: 10px; + padding: 20px; + } + """) + else: + self.time_label.setStyleSheet(""" + QLabel { + font-size: 72px; + font-weight: bold; + color: #3498db; + font-family: 'Courier New', monospace; + background-color: #ecf0f1; + border-radius: 10px; + padding: 20px; + } + """) + + def play_alert(self): + """播放告警提示音""" + # 使用系统提示音 + # 注意:这里使用一个简单的实现 + # 实际使用中,你可以替换为自定义音频文件 + try: + # 尝试播放系统提示音 + QApplication.beep() + + # 设置循环播放2次(总共3次) + self.alert_loop_count = 0 + self.alert_timer = QTimer() + self.alert_timer.timeout.connect(self.play_alert_loop) + self.alert_timer.start(1000) # 每秒播放一次 + + except Exception as e: + print(f"播放告警音失败: {e}") + + def play_alert_loop(self): + """循环播放告警""" + if self.alert_loop_count < 2: + QApplication.beep() + self.alert_loop_count += 1 + else: + self.alert_timer.stop() + + def show_finish(self): + """显示完成提示""" + # 调整窗口大小为缩小模式(150x50像素) + self.resize(150, 50) + + # 移动窗口位置到距离top 30px,距离右边边缘30px + screen = QApplication.primaryScreen().geometry() + screen_width = screen.width() + screen_height = screen.height() + new_x = screen_width - 150 - 30 # 距离右边30px + new_y = 30 # 距离top 30px + self.move(new_x, new_y) + + # 确保窗口在最前面 + self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint) + self.show() + + self.time_label.hide() + self.finish_label.show() + + # 开始闪烁动画 + self.blink_state = True + self.blink_timer.start(500) # 每500ms切换一次 + + # 播放提示音 + QApplication.beep() + + self.btn_pause.setEnabled(False) + + def toggle_blink(self): + """切换闪烁状态""" + if self.blink_state: + self.finish_label.setStyleSheet(""" + QLabel { + font-size: 48px; + font-weight: bold; + color: #e74c3c; + background-color: #fee; + border-radius: 10px; + padding: 20px; + } + """) + else: + self.finish_label.setStyleSheet(""" + QLabel { + font-size: 52px; + font-weight: bold; + color: #c0392b; + background-color: #fadbd8; + border-radius: 10px; + padding: 25px; + } + """) + self.blink_state = not self.blink_state + + def toggle_button_group(self): + """切换按钮区域的折叠/展开状态""" + # 如果当前是微缩状态,点击箭头暂停倒计时并切换回正常状态 + if self.current_state == "mini": + # 暂停倒计时 + self.timer.stop() + self.is_running = False + self.btn_pause.setText("暂停") + + # 切换回正常状态 + self.switch_to_normal_state() + return + + # 如果当前是正常状态 + if self.button_group.isHidden(): + self.button_group.show() + self.collapse_button.setText("▼") + + # 如果正在运行倒计时,恢复原始窗口大小 + if self.is_running: + self.switch_to_normal_state() + else: + self.button_group.hide() + self.collapse_button.setText("▶") + + # 如果正在运行倒计时,暂停倒计时并切换到微缩状态 + if self.is_running: + # 暂停倒计时 + self.timer.stop() + self.is_running = False + + # 切换到微缩状态 + self.switch_to_mini_state() + + # 按钮文本保持为"暂停",因为倒计时已经被暂停 + self.btn_pause.setText("暂停") + + def open_config(self): + """打开配置对话框""" + dialog = ConfigDialog(self) + + # 加载当前配置 + dialog.custom_time_spin.setValue(self.config["custom_seconds"]) + dialog.alert_time_spin.setValue(self.config["alert_seconds"]) + dialog.topmost_checkbox.setChecked(self.config["topmost"]) + dialog.opacity_slider.setValue(self.config["opacity"]) + + if dialog.exec() == QDialog.Accepted: + # 保存配置 + self.config["custom_seconds"] = dialog.custom_time_spin.value() + self.config["alert_seconds"] = dialog.alert_time_spin.value() + self.config["topmost"] = dialog.topmost_checkbox.isChecked() + self.config["opacity"] = dialog.opacity_slider.value() + + self.save_config() + self.apply_config() + + # 启动自定义倒计时 + self.start_countdown(self.config["custom_seconds"]) + + +def main(): + """主函数""" + app = QApplication(sys.argv) + + # 设置应用程序样式 + app.setStyle("Fusion") + + window = CountdownTimer() + window.show() + + sys.exit(app.exec()) + + +if __name__ == "__main__": + main() diff --git a/要求.txt b/要求.txt new file mode 100644 index 0000000..4477f6f --- /dev/null +++ b/要求.txt @@ -0,0 +1,18 @@ +目的:写一个python语言的,pyside6库作为界面的应用程序。 +功能:倒计时显示和提醒。 +界面需求:整体要美观大方。 +1. 窗口无标题栏,可以通过点击并拖动任何位置移动窗口 +2. 倒计时显示区域:显示分和秒的倒计时,字体大且醒目 +3. 界面分为2个状态: + a. 正常状态:显示时间,点击箭头,显示按钮区域,再点击箭头,按钮区域折叠 + b. 微缩状态:点击"5分钟"后,延迟2秒,界面改为微缩状态,只有时间区域和向下箭头 +4. 微缩状态详情: + - 窗口长为200px,高为60px + - 距离top为50px,距离屏幕右边留出空白200px的距离 + - 点击向下箭头,回到正常状态的位置和大小 +5. 快捷按钮:第一个按钮是"5分钟",第二个按钮是"6分钟",第三个按钮是"其它" +6. 其它按钮功能:打开配置页面,可以设置自定义倒计时时间、提前告警时间、窗口置顶选项、透明度设置 +7. 告警功能:倒计时结束前设置的秒数时播放告警提示音,循环3次 +8. 倒计时结束后:显示"时间已到"文字,带有跳动和闪动效果 +9. 配置对话框:增加退出按钮,只有通过此按钮才能退出程序 +10. 测试要求:使用pyqt-test库作为gui程序的测试工具。 \ No newline at end of file