今天给大家安利一款超酷的赛博朋克风格时钟,让你的桌面瞬间充满未来感!(记得往下拉,代码在最后面,具有逐行注释,做到简单易懂)
特色功能:
1 赛博朋克风格设计
- 霓虹蓝色渐变背景
- 发光边框效果
- 动态刻度显示
- 智能指针系统
2 智能闹钟功能
- 双击设置闹钟时间
- 动态红点提醒
- 呼吸效果动画
- 闹钟触发时震动提醒
3 交互体验
- 左键点击实现弹性缩放
- 右键菜单控制
- 支持拖拽移动
- 半透明效果
4 细节设计
- 实时时间显示
- 动态刻度变化
- 指针流光效果
- 闹钟位置指示
使用场景:
- 桌面时钟
- 工作提醒
- 时间管理
- 装饰桌面
亮点:
- 界面设计充满未来感
- 操作简单直观
- 动画效果流畅
- 功能实用性强
设计风格:
- 赛博朋克元素
- 霓虹灯效果
- 动态交互
- 科技感十足
技术特点:
- 基于PyQt5开发
- 流畅的动画效果
- 精确的时间计算
- 优雅的代码结构
使用体验:
- 界面简洁大方
- 操作便捷直观
- 视觉效果出众
- 功能实用性强
适用人群:
- 科技爱好者
- 桌面美化控
- 时间管理达人
- 赛博朋克迷
总结:
这款赛博朋克风格时钟不仅实用,更是一件艺术品。它将时间显示与未来科技完美结合,让你的桌面充满科技感和未来感。无论是工作提醒还是装饰桌面,都是一个不错的选择!
#赛博朋克 #时钟 #桌面美化 #科技感 #时间管理 #Python #PyQt5
记得点赞关注,更多精彩内容等你来发现!
import sys # 导入系统模块
import math # 导入数学模块
import random # 导入随机数模块
from datetime import datetime, timedelta # 导入日期时间模块和时间差模块
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout, # 导入PyQt5界面组件
QLabel, QTimeEdit, QPushButton, QMenu, QAction,
QMessageBox, QDialog, QComboBox, QCheckBox, QGroupBox,
QRadioButton, QSlider, QFrame)
from PyQt5.QtCore import Qt, QTimer, QTime, QDateTime, QPoint, QSize, QPropertyAnimation, QEasingCurve # 导入PyQt5核心模块
from PyQt5.QtCore import QParallelAnimationGroup, QSequentialAnimationGroup, QAbstractAnimation, QPointF # 导入PyQt5动画相关模块
from PyQt5.QtGui import QPainter, QColor, QPen, QFont, QBrush, QPainterPath, QLinearGradient # 导入PyQt5绘图模块
class AlarmDialog(QDialog): # 定义闹钟设置对话框类
def __init__(self, parent=None): # 初始化方法
super().__init__(parent) # 调用父类初始化方法
self.setWindowTitle("设置闹钟") # 设置窗口标题
self.resize(320, 280) # 设置窗口大小
# 设置样式 - CSS样式表
self.setStyleSheet("""
QDialog { /* 对话框样式 */
background-color: #f5f5f5; /* 背景颜色 */
border-radius: 10px; /* 边框圆角 */
border: 1px solid #dcdcdc; /* 边框样式 */
}
QLabel { /* 标签样式 */
font-family: 'Microsoft YaHei', sans-serif; /* 字体 */
color: #333333; /* 字体颜色 */
font-size: 12px; /* 字体大小 */
}
QTimeEdit { /* 时间编辑器样式 */
padding: 8px; /* 内边距 */
border: 1px solid #cccccc; /* 边框样式 */
border-radius: 5px; /* 边框圆角 */
background-color: white; /* 背景颜色 */
selection-background-color: #0078d7; /* 选中背景颜色 */
font-size: 14px; /* 字体大小 */
min-height: 25px; /* 最小高度 */
}
QPushButton { /* 按钮样式 */
background-color: #0078d7; /* 背景颜色 */
color: white; /* 字体颜色 */
border-radius: 5px; /* 边框圆角 */
padding: 8px 16px; /* 内边距 */
font-weight: bold; /* 字体粗细 */
min-width: 80px; /* 最小宽度 */
min-height: 30px; /* 最小高度 */
}
QPushButton:hover { /* 按钮悬停样式 */
background-color: #1982d8; /* 悬停时背景颜色 */
}
QPushButton:pressed { /* 按钮按下样式 */
background-color: #006cc1; /* 按下时背景颜色 */
}
QPushButton#cancelButton { /* 取消按钮样式 */
background-color: #f0f0f0; /* 背景颜色 */
color: #333333; /* 字体颜色 */
border: 1px solid #cccccc; /* 边框样式 */
}
QPushButton#cancelButton:hover { /* 取消按钮悬停样式 */
background-color: #e5e5e5; /* 悬停时背景颜色 */
}
QComboBox, QCheckBox { /* 下拉框和复选框样式 */
padding: 5px; /* 内边距 */
border: 1px solid #cccccc; /* 边框样式 */
border-radius: 5px; /* 边框圆角 */
background-color: white; /* 背景颜色 */
min-height: 25px; /* 最小高度 */
}
QGroupBox { /* 组框样式 */
font-weight: bold; /* 字体粗细 */
border: 1px solid #cccccc; /* 边框样式 */
border-radius: 5px; /* 边框圆角 */
margin-top: 10px; /* 上边距 */
padding-top: 10px; /* 上内边距 */
}
QGroupBox::title { /* 组框标题样式 */
subcontrol-origin: margin; /* 子控件原点 */
subcontrol-position: top center; /* 子控件位置 */
padding: 0 5px; /* 内边距 */
}
QRadioButton { /* 单选按钮样式 */
padding: 3px; /* 内边距 */
}
QFrame#line { /* 分割线样式 */
color: #cccccc; /* 颜色 */
}
""")
main_layout = QVBoxLayout() # 创建主垂直布局
main_layout.setSpacing(15) # 设置布局间距
main_layout.setContentsMargins(20, 20, 20, 20) # 设置布局边距
# 时间设置区域
time_group = QGroupBox("时间设置") # 创建时间设置组框
time_layout = QVBoxLayout() # 创建时间设置垂直布局
time_label = QLabel("请选择闹钟时间:") # 创建标签
self.time_edit = QTimeEdit() # 创建时间编辑器
self.time_edit.setDisplayFormat("HH:mm:ss") # 设置时间显示格式
self.time_edit.setTime(QTime.currentTime().addSecs(60)) # 设置默认时间为当前时间加一分钟
self.time_edit.setAlignment(Qt.AlignCenter) # 设置文本居中对齐
time_layout.addWidget(time_label) # 添加标签到布局
time_layout.addWidget(self.time_edit) # 添加时间编辑器到布局
time_group.setLayout(time_layout) # 设置组框布局
# 提醒选项区域
options_group = QGroupBox("提醒选项") # 创建提醒选项组框
options_layout = QVBoxLayout() # 创建提醒选项垂直布局
# 重复选项
repeat_layout = QHBoxLayout() # 创建重复选项水平布局
repeat_label = QLabel("重复:") # 创建重复标签
self.repeat_combo = QComboBox() # 创建下拉框
repeat_options = ["不重复", "每天", "工作日", "周末"] # 重复选项列表
self.repeat_combo.addItems(repeat_options) # 添加选项到下拉框
repeat_layout.addWidget(repeat_label) # 添加标签到布局
repeat_layout.addWidget(self.repeat_combo) # 添加下拉框到布局
# 音量设置
volume_layout = QHBoxLayout() # 创建音量设置水平布局
volume_label = QLabel("音量:") # 创建音量标签
self.volume_slider = QSlider(Qt.Horizontal) # 创建水平滑块
self.volume_slider.setMinimum(0) # 设置最小值
self.volume_slider.setMaximum(100) # 设置最大值
self.volume_slider.setValue(80) # 设置默认值
volume_layout.addWidget(volume_label) # 添加标签到布局
volume_layout.addWidget(self.volume_slider) # 添加滑块到布局
# 添加一条分隔线
line = QFrame() # 创建框架
line.setObjectName("line") # 设置对象名
line.setFrameShape(QFrame.HLine) # 设置框架形状为水平线
line.setFrameShadow(QFrame.Sunken) # 设置框架阴影
# 添加到options布局
options_layout.addLayout(repeat_layout) # 添加重复选项布局到主布局
options_layout.addLayout(volume_layout) # 添加音量设置布局到主布局
options_group.setLayout(options_layout) # 设置选项组的布局
# 标签输入
label_layout = QHBoxLayout() # 创建标签输入水平布局
label_layout.addWidget(QLabel("闹钟标签:")) # 添加标签
self.label_edit = QComboBox() # 创建下拉框
self.label_edit.setEditable(True) # 设置为可编辑
self.label_edit.addItems(["起床", "午休", "工作", "吃药", "自定义"]) # 添加预设选项
label_layout.addWidget(self.label_edit) # 添加到布局
# 按钮布局
button_layout = QHBoxLayout() # 创建按钮水平布局
button_layout.setSpacing(10) # 设置间距
self.set_button = QPushButton("设置") # 创建设置按钮
self.set_button.clicked.connect(self.accept) # 连接点击信号到接受槽
self.cancel_button = QPushButton("取消") # 创建取消按钮
self.cancel_button.setObjectName("cancelButton") # 设置对象名
self.cancel_button.clicked.connect(self.reject) # 连接点击信号到拒绝槽
button_layout.addStretch() # 添加弹性空间
button_layout.addWidget(self.cancel_button) # 添加取消按钮
button_layout.addWidget(self.set_button) # 添加设置按钮
# 添加所有部件到主布局
main_layout.addWidget(time_group) # 添加时间设置组
main_layout.addWidget(options_group) # 添加选项组
main_layout.addLayout(label_layout) # 添加标签布局
main_layout.addStretch() # 添加弹性空间
main_layout.addWidget(line) # 添加分隔线
main_layout.addLayout(button_layout) # 添加按钮布局
self.setLayout(main_layout) # 设置对话框的主布局
def get_alarm_time(self): # 获取闹钟时间方法
return self.time_edit.time() # 返回时间编辑器的时间
def get_alarm_label(self): # 获取闹钟标签方法
return self.label_edit.currentText() # 返回标签编辑器的当前文本
def get_alarm_repeat(self): # 获取闹钟重复设置方法
return self.repeat_combo.currentText() # 返回重复下拉框的当前文本
def get_alarm_volume(self): # 获取闹钟音量方法
return self.volume_slider.value() # 返回音量滑块的当前值
class Clock(QWidget):
def __init__(self):
super().__init__()
self.alarm_time = None
self.alarm_enabled = False
self.alarm_label = "" # 初始化闹钟标签为空
self.alarm_repeat = "不重复" # 初始化闹钟重复模式为不重复
self.alarm_volume = 80 # 初始化闹钟音量为80
self.is_enlarged = False # 初始化闹钟未放大
self.original_size = QSize(200, 200) # 设置原始大小为200x200
self.is_dragging = False # 初始化未拖动状态
self.drag_position = None # 初始化拖动位置为空
self.is_mouse_over = False # 初始化鼠标未悬停状态
self.explosion_particles = [] # 初始化爆炸粒子列表
self.explosion_animation_active = False # 初始化爆炸动画未激活
self.original_position = None # 初始化原始位置为空
self.clock_style = 0 # 初始化表盘风格,0=黑色金属, 1=经典白色, 2=夜光蓝色
self.init_ui() # 调用界面初始化方法
def init_ui(self): # 界面初始化方法
self.setWindowTitle('闹钟') # 设置窗口标题
self.resize(self.original_size) # 调整窗口大小
# 设置窗口样式
self.setStyleSheet("""
background-color: #f0f0f0; /* 背景颜色 */
border-radius: 100px; /* 边框圆角 */
""")
# 创建定时器更新时间
self.timer = QTimer(self) # 创建定时器
self.timer.timeout.connect(self.update) # 连接超时信号到更新方法
self.timer.start(1000) # 设置1秒更新一次
# 为鼠标事件设置追踪
self.setMouseTracking(True) # 启用鼠标追踪
# 设置窗口标志以允许自定义样式
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) # 设置无边框和置顶
self.setAttribute(Qt.WA_TranslucentBackground) # 设置背景透明
def paintEvent(self, event): # 绘制事件处理
painter = QPainter(self) # 创建画家对象
painter.setRenderHint(QPainter.Antialiasing) # 启用抗锯齿
# 获取当前大小
width = self.width() # 获取宽度
height = self.height() # 获取高度
# 计算中心点和半径
center_x = width / 2 # 计算中心x坐标
center_y = height / 2 # 计算中心y坐标
radius = min(center_x, center_y) - 10 # 计算半径
# 设置透明度 - 鼠标悬停时变半透明
background_opacity = 180 if self.is_mouse_over else 255 # 根据鼠标悬停状态设置透明度
# 根据表盘风格绘制不同的表盘
if self.clock_style == 0: # 黑色金属风格
# 创建黑色金属渐变背景
gradient = QLinearGradient(0, 0, width, height) # 创建线性渐变
gradient.setColorAt(0, QColor(40, 40, 45, background_opacity)) # 设置渐变起始颜色(深灰黑)
gradient.setColorAt(0.4, QColor(20, 20, 25, background_opacity)) # 设置渐变中间颜色(近黑色)
gradient.setColorAt(1, QColor(10, 10, 15, background_opacity)) # 设置渐变结束颜色(纯黑)
# 绘制表盘背景
painter.setPen(Qt.NoPen) # 设置无边框
painter.setBrush(gradient) # 设置渐变填充
painter.drawEllipse(QPoint(center_x, center_y), radius, radius) # 绘制圆形表盘
# 绘制金属质感边框
# 外环 - 金属光泽效果
metal_pen = QPen(QColor(70, 70, 75, background_opacity), 3) # 创建金属质感画笔
painter.setPen(metal_pen) # 设置画笔
painter.setBrush(Qt.NoBrush) # 设置无填充
painter.drawEllipse(QPoint(center_x, center_y), radius, radius) # 绘制外边框
# 内环 - 增强金属质感
metal_pen2 = QPen(QColor(100, 100, 110, background_opacity), 1) # 创建更亮的金属边框画笔
painter.setPen(metal_pen2) # 设置画笔
painter.drawEllipse(QPoint(center_x, center_y), radius - 3, radius - 3) # 绘制内边框
# 小时数字颜色
hour_number_color = QColor(210, 210, 220, background_opacity) # 小时数字颜色
# 刻度颜色
major_tick_color = QColor(180, 180, 190, background_opacity) # 主刻度颜色
minor_tick_color = QColor(140, 140, 150, background_opacity) # 次刻度颜色
# 指针颜色
hour_hand_color = QColor(220, 220, 230, background_opacity) # 时针颜色
minute_hand_color = QColor(180, 200, 255, background_opacity) # 分针颜色
second_hand_color = QColor(255, 90, 90, background_opacity) # 秒针颜色
# 中心点颜色
center_dot_color = QColor(230, 230, 240, background_opacity) # 中心点颜色
inner_dot_color = QColor(40, 40, 45, background_opacity) # 内部点颜色
# 文本颜色
text_color = QColor(200, 200, 210, background_opacity) # 文本颜色
alarm_color = QColor(255, 60, 60, background_opacity) # 闹钟指示器颜色
alarm_text_color = QColor(255, 80, 80, background_opacity) # 闹钟文本颜色
elif self.clock_style == 1: # 经典白色风格
# 创建白色渐变背景
gradient = QLinearGradient(0, 0, width, height) # 创建线性渐变
gradient.setColorAt(0, QColor(250, 250, 250, background_opacity)) # 设置渐变起始颜色(白色)
gradient.setColorAt(1, QColor(240, 240, 240, background_opacity)) # 设置渐变结束颜色(淡灰白)
# 绘制表盘背景
painter.setPen(Qt.NoPen) # 设置无边框
painter.setBrush(gradient) # 设置渐变填充
painter.drawEllipse(QPoint(center_x, center_y), radius, radius) # 绘制圆形表盘
# 绘制简约边框
classic_pen = QPen(QColor(180, 180, 180, background_opacity), 2) # 创建边框画笔
painter.setPen(classic_pen) # 设置画笔
painter.setBrush(Qt.NoBrush) # 设置无填充
painter.drawEllipse(QPoint(center_x, center_y), radius, radius) # 绘制边框
# 小时数字颜色
hour_number_color = QColor(50, 50, 50, background_opacity) # 小时数字颜色
# 刻度颜色
major_tick_color = QColor(80, 80, 80, background_opacity) # 主刻度颜色
minor_tick_color = QColor(120, 120, 120, background_opacity) # 次刻度颜色
# 指针颜色
hour_hand_color = QColor(0, 0, 0, background_opacity) # 时针颜色
minute_hand_color = QColor(30, 30, 200, background_opacity) # 分针颜色
second_hand_color = QColor(200, 0, 0, background_opacity) # 秒针颜色
# 中心点颜色
center_dot_color = QColor(50, 50, 50, background_opacity) # 中心点颜色
inner_dot_color = QColor(180, 180, 180, background_opacity) # 内部点颜色
# 文本颜色
text_color = QColor(60, 60, 60, background_opacity) # 文本颜色
alarm_color = QColor(220, 0, 0, background_opacity) # 闹钟指示器颜色
alarm_text_color = QColor(220, 0, 0, background_opacity) # 闹钟文本颜色
else: # 夜光蓝色风格
# 创建蓝色渐变背景
gradient = QLinearGradient(0, 0, width, height) # 创建线性渐变
gradient.setColorAt(0, QColor(15, 25, 55, background_opacity)) # 设置渐变起始颜色(深蓝)
gradient.setColorAt(0.5, QColor(20, 30, 70, background_opacity)) # 设置渐变中间颜色(中蓝)
gradient.setColorAt(1, QColor(10, 20, 45, background_opacity)) # 设置渐变结束颜色(暗蓝)
# 绘制表盘背景
painter.setPen(Qt.NoPen) # 设置无边框
painter.setBrush(gradient) # 设置渐变填充
painter.drawEllipse(QPoint(center_x, center_y), radius, radius) # 绘制圆形表盘
# 绘制星空边框
glow_pen = QPen(QColor(100, 150, 255, background_opacity), 2) # 创建发光边框画笔
painter.setPen(glow_pen) # 设置画笔
painter.setBrush(Qt.NoBrush) # 设置无填充
painter.drawEllipse(QPoint(center_x, center_y), radius, radius) # 绘制边框
# 绘制小星星(点缀)
painter.setPen(Qt.NoPen) # 设置无边框
for i in range(20): # 绘制20颗星星
# 随机位置
star_angle = random.uniform(0, 2 * math.pi) # 随机角度
star_distance = random.uniform(0.2, 0.9) * radius # 随机距离
star_x = center_x + star_distance * math.cos(star_angle) # 星星x坐标
star_y = center_y + star_distance * math.sin(star_angle) # 星星y坐标
# 随机大小
star_size = random.uniform(1, 2) # 随机星星大小
# 随机亮度
star_brightness = random.randint(180, 255) # 随机亮度
# 绘制星星
painter.setBrush(QBrush(QColor(star_brightness, star_brightness, star_brightness, background_opacity))) # 设置星星颜色
painter.drawEllipse(QPointF(star_x, star_y), star_size, star_size) # 绘制星星
# 小时数字颜色
hour_number_color = QColor(130, 200, 255, background_opacity) # 小时数字颜色
# 刻度颜色
major_tick_color = QColor(100, 180, 255, background_opacity) # 主刻度颜色
minor_tick_color = QColor(60, 120, 200, background_opacity) # 次刻度颜色
# 指针颜色
hour_hand_color = QColor(150, 220, 255, background_opacity) # 时针颜色
minute_hand_color = QColor(100, 180, 255, background_opacity) # 分针颜色
second_hand_color = QColor(200, 230, 255, background_opacity) # 秒针颜色
# 中心点颜色
center_dot_color = QColor(150, 220, 255, background_opacity) # 中心点颜色
inner_dot_color = QColor(20, 40, 80, background_opacity) # 内部点颜色
# 文本颜色
text_color = QColor(120, 200, 255, background_opacity) # 文本颜色
alarm_color = QColor(255, 150, 100, background_opacity) # 闹钟指示器颜色
alarm_text_color = QColor(255, 150, 100, background_opacity) # 闹钟文本颜色
# 绘制分钟刻度线
for i in range(60): # 循环60次绘制分钟刻度
angle = math.radians(6 * i - 90) # 计算每分钟的角度(每分钟6度)
is_five_minute = i % 5 == 0 # 判断是否为5分钟刻度
# 设置刻度画笔 - 5分钟粗刻度
if is_five_minute:
# 5分钟粗刻度
painter.setPen(QPen(major_tick_color, 2.5, Qt.SolidLine, Qt.RoundCap))
scale_outer = 0.95 # 外侧位置比例
scale_inner = 0.85 # 内侧位置比例
else:
# 普通分钟细刻度
painter.setPen(QPen(minor_tick_color, 1, Qt.SolidLine, Qt.RoundCap))
scale_outer = 0.95 # 外侧位置比例
scale_inner = 0.90 # 内侧位置比例(细刻度短一些)
# 计算刻度线起止点坐标
outer_x = center_x + radius * scale_outer * math.cos(angle) # 计算外侧x坐标
outer_y = center_y + radius * scale_outer * math.sin(angle) # 计算外侧y坐标
inner_x = center_x + radius * scale_inner * math.cos(angle) # 计算内侧x坐标
inner_y = center_y + radius * scale_inner * math.sin(angle) # 计算内侧y坐标
# 绘制刻度线
painter.drawLine(int(outer_x), int(outer_y), int(inner_x), int(inner_y)) # 绘制刻度线
# 绘制小时标记/数字
font = QFont("Microsoft YaHei") # 设置微软雅黑字体
font.setPointSize(11) # 设置字体大小
font.setBold(True) # 设置粗体
painter.setFont(font) # 应用字体
for i in range(12): # 循环绘制12个小时标记
angle = math.radians(30 * i - 90) # 计算角度(弧度)
# 绘制小时数字 - 在粗刻度内侧
x = center_x + (radius - 25) * math.cos(angle) # 计算数字x坐标
y = center_y + (radius - 25) * math.sin(angle) # 计算数字y坐标
hour_text = str(i if i > 0 else 12) # 获取小时文本,0点显示为12
text_width = painter.fontMetrics().width(hour_text) # 获取文本宽度
text_height = painter.fontMetrics().height() # 获取文本高度
# 使用对应风格颜色绘制数字
painter.setPen(QPen(hour_number_color, 1)) # 设置画笔
painter.drawText(int(x - text_width / 2), int(y + text_height / 3), hour_text) # 居中绘制文本
# 获取当前时间
current_time = datetime.now().time() # 获取当前时间
hour = current_time.hour % 12 # 获取当前小时(12小时制)
minute = current_time.minute # 获取当前分钟
second = current_time.second # 获取当前秒钟
# 计算时针角度 (小时 + 分钟的贡献)
hour_angle = math.radians((hour + minute / 60) * 30 - 90) # 计算时针角度
# 计算分针角度
minute_angle = math.radians(minute * 6 - 90) # 计算分针角度
# 计算秒针角度
second_angle = math.radians(second * 6 - 90) # 计算秒针角度
# 绘制时针
hour_length = radius * 0.5 # 设置时针长度
painter.setPen(QPen(hour_hand_color, 4, Qt.SolidLine, Qt.RoundCap)) # 设置时针画笔
painter.drawLine( # 绘制时针线段
int(center_x), int(center_y), # 起点坐标
int(center_x + hour_length * math.cos(hour_angle)), # 终点x坐标
int(center_y + hour_length * math.sin(hour_angle)) # 终点y坐标
)
# 绘制分针
minute_length = radius * 0.7 # 设置分针长度
painter.setPen(QPen(minute_hand_color, 3, Qt.SolidLine, Qt.RoundCap)) # 设置分针画笔
painter.drawLine( # 绘制分针线段
int(center_x), int(center_y), # 起点坐标
int(center_x + minute_length * math.cos(minute_angle)), # 终点x坐标
int(center_y + minute_length * math.sin(minute_angle)) # 终点y坐标
)
# 绘制秒针
second_length = radius * 0.8 # 设置秒针长度
painter.setPen(QPen(second_hand_color, 2, Qt.SolidLine, Qt.RoundCap)) # 设置秒针画笔
painter.drawLine( # 绘制秒针线段
int(center_x), int(center_y), # 起点坐标
int(center_x + second_length * math.cos(second_angle)), # 终点x坐标
int(center_y + second_length * math.sin(second_angle)) # 终点y坐标
)
# 绘制中心点
painter.setPen(Qt.NoPen) # 设置无边框
painter.setBrush(QBrush(center_dot_color)) # 设置中心点颜色
painter.drawEllipse(QPoint(int(center_x), int(center_y)), 5, 5) # 绘制中心圆点
# 二级中心点
painter.setBrush(QBrush(inner_dot_color)) # 设置内部点颜色
painter.drawEllipse(QPoint(int(center_x), int(center_y)), 2, 2) # 绘制内部圆点
# 显示当前时间文本
painter.setPen(QPen(text_color)) # 设置文本画笔
font = QFont("Microsoft YaHei") # 设置微软雅黑字体
font.setPointSize(8) # 设置字体大小
painter.setFont(font) # 应用字体
time_text = current_time.strftime("%H:%M:%S") # 格式化当前时间
text_width = painter.fontMetrics().width(time_text) # 获取文本宽度
painter.drawText(int(center_x - text_width / 2), int(center_y + radius * 0.4), time_text) # 居中绘制时间文本
# 如果设置了闹钟,绘制闹钟指示器
if self.alarm_enabled and self.alarm_time: # 如果启用了闹钟并且设置了闹钟时间
alarm_hour = self.alarm_time.hour() % 12 # 获取闹钟小时
alarm_minute = self.alarm_time.minute() # 获取闹钟分钟
alarm_angle = math.radians((alarm_hour + alarm_minute / 60) * 30 - 90) # 计算闹钟角度
# 绘制闹钟指示器(一个小点)
painter.setPen(Qt.NoPen) # 设置无边框
painter.setBrush(QBrush(alarm_color)) # 设置闹钟指示器颜色
alarm_x = center_x + (radius - 45) * math.cos(alarm_angle) # 计算指示器x坐标
alarm_y = center_y + (radius - 45) * math.sin(alarm_angle) # 计算指示器y坐标
painter.drawEllipse(QPoint(int(alarm_x), int(alarm_y)), 4, 4) # 绘制指示器圆点
# 显示闹钟时间文本
painter.setPen(QPen(alarm_text_color)) # 设置闹钟文本颜色
font = QFont("Microsoft YaHei") # 设置微软雅黑字体
font.setPointSize(8) # 设置字体大小
painter.setFont(font) # 应用字体
alarm_text = f"{self.alarm_time.toString('hh:mm')}" # 格式化闹钟时间
if self.alarm_label: # 如果设置了闹钟标签
alarm_text += f" ({self.alarm_label})" # 添加标签到显示文本
text_width = painter.fontMetrics().width(alarm_text) # 获取文本宽度
painter.drawText(int(center_x - text_width / 2), int(center_y - radius * 0.4), alarm_text) # 居中绘制闹钟文本
# 检查是否到了闹钟时间
now = QTime.currentTime() # 获取当前时间
if (now.hour() == self.alarm_time.hour() and # 如果小时相同
now.minute() == self.alarm_time.minute() and # 如果分钟相同
now.second() == 0): # 如果秒钟为0
self.trigger_alarm() # 触发闹钟
def mouseDoubleClickEvent(self, event): # 鼠标双击事件处理
# 双击设置闹钟
dialog = AlarmDialog(self) # 创建闹钟设置对话框
if dialog.exec_(): # 如果用户点击了确定
self.alarm_time = dialog.get_alarm_time() # 获取设置的闹钟时间
self.alarm_label = dialog.get_alarm_label() # 获取设置的闹钟标签
self.alarm_repeat = dialog.get_alarm_repeat() # 获取设置的闹钟重复模式
self.alarm_volume = dialog.get_alarm_volume() # 获取设置的闹钟音量
self.alarm_enabled = True # 启用闹钟
msg = f"闹钟已设置为 {self.alarm_time.toString('hh:mm:ss')}" # 构建提示信息
if self.alarm_label: # 如果设置了标签
msg += f"\n标签: {self.alarm_label}" # 添加标签信息
if self.alarm_repeat != "不重复": # 如果设置了重复
msg += f"\n重复: {self.alarm_repeat}" # 添加重复信息
QMessageBox.information(self, "闹钟设置", msg) # 显示设置成功信息
def mousePressEvent(self, event): # 鼠标按下事件处理
# 左键点击放大效果
if event.button() == Qt.LeftButton: # 如果按下的是左键
self.enlarge_clock() # 放大/缩小闹钟
# 记录拖动开始位置
self.is_dragging = True # 设置为拖动状态
self.drag_position = event.globalPos() - self.frameGeometry().topLeft() # 计算拖动位置差
event.accept() # 接受事件
def mouseMoveEvent(self, event): # 鼠标移动事件处理
# 长按拖动
if self.is_dragging and event.buttons() == Qt.LeftButton: # 如果正在拖动且左键按下
self.move(event.globalPos() - self.drag_position) # 移动窗口位置
event.accept() # 接受事件
# 检测鼠标悬停状态
self.is_mouse_over = True # 设置鼠标悬停状态
self.update() # 更新界面以反映透明度变化
def mouseReleaseEvent(self, event): # 鼠标释放事件处理
if event.button() == Qt.LeftButton: # 如果释放的是左键
self.is_dragging = False # 结束拖动状态
def leaveEvent(self, event): # 鼠标离开事件处理
# 当鼠标移出窗口时
self.is_mouse_over = False # 清除鼠标悬停状态
self.update() # 更新界面以反映透明度变化
def contextMenuEvent(self, event): # 右键菜单事件处理
# 右键菜单
menu = QMenu(self) # 创建菜单
# 添加风格子菜单
style_menu = QMenu("表盘风格", self) # 创建表盘风格子菜单
# 添加三种风格选项
metal_action = QAction("黑色金属", self) # 创建黑色金属风格动作
metal_action.setCheckable(True) # 设置为可勾选
metal_action.setChecked(self.clock_style == 0) # 根据当前风格设置勾选状态
metal_action.triggered.connect(lambda: self.change_clock_style(0)) # 连接到切换风格方法
classic_action = QAction("经典白色", self) # 创建经典白色风格动作
classic_action.setCheckable(True) # 设置为可勾选
classic_action.setChecked(self.clock_style == 1) # 根据当前风格设置勾选状态
classic_action.triggered.connect(lambda: self.change_clock_style(1)) # 连接到切换风格方法
neon_action = QAction("夜光蓝色", self) # 创建夜光蓝色风格动作
neon_action.setCheckable(True) # 设置为可勾选
neon_action.setChecked(self.clock_style == 2) # 根据当前风格设置勾选状态
neon_action.triggered.connect(lambda: self.change_clock_style(2)) # 连接到切换风格方法
# 添加动作到风格子菜单
style_menu.addAction(metal_action) # 添加黑色金属选项
style_menu.addAction(classic_action) # 添加经典白色选项
style_menu.addAction(neon_action) # 添加夜光蓝色选项
# 添加风格子菜单到主菜单
menu.addMenu(style_menu) # 添加风格子菜单
# 添加分隔线
menu.addSeparator() # 添加分隔线
if self.alarm_enabled: # 如果闹钟已启用
disable_action = QAction("禁用闹钟", self) # 创建禁用闹钟动作
disable_action.triggered.connect(self.disable_alarm) # 连接动作信号到禁用闹钟方法
menu.addAction(disable_action) # 添加动作到菜单
exit_action = QAction("退出", self) # 创建退出动作
exit_action.triggered.connect(self.confirm_exit) # 连接动作信号到确认退出方法
menu.addAction(exit_action) # 添加动作到菜单
menu.exec_(event.globalPos()) # 在鼠标位置显示菜单
def enlarge_clock(self): # 放大/缩小闹钟方法
if not self.is_enlarged: # 如果当前未放大
# 放大
target_size = QSize(int(self.original_size.width() * 1.2), # 计算目标宽度
int(self.original_size.height() * 1.2)) # 计算目标高度
self.animate_resize(target_size) # 调用动画调整大小
self.is_enlarged = True # 设置为已放大状态
else: # 如果当前已放大
# 恢复原大小
self.animate_resize(self.original_size) # 调用动画恢复原始大小
self.is_enlarged = False # 设置为未放大状态
def animate_resize(self, target_size): # 大小动画方法
# 创建大小动画
self.animation = QPropertyAnimation(self, b"size") # 创建大小属性动画
self.animation.setDuration(300) # 设置动画持续时间
self.animation.setStartValue(self.size()) # 设置起始大小
self.animation.setEndValue(target_size) # 设置目标大小
self.animation.setEasingCurve(QEasingCurve.OutCubic) # 设置缓动曲线
self.animation.start() # 开始动画
def disable_alarm(self): # 禁用闹钟方法
self.alarm_enabled = False # 设置闹钟为禁用状态
QMessageBox.information(self, "闹钟已禁用", "闹钟已被禁用") # 显示禁用成功信息
def confirm_exit(self): # 确认退出方法
reply = QMessageBox.question( # 显示询问对话框
self, '确认退出', # 设置对话框标题
'你确定要退出闹钟程序吗?', # 设置对话框内容
QMessageBox.Yes | QMessageBox.No, # 设置按钮选项
QMessageBox.No # 设置默认按钮
)
if reply == QMessageBox.Yes: # 如果用户点击了是
QApplication.quit() # 退出应用程序
def trigger_alarm(self): # 触发闹钟方法
# 保存原始位置用于动画后恢复
self.original_position = self.pos() # 记录当前位置
# 开始震动和爆炸效果
self.start_explosion_animation() # 启动爆炸动画
# 显示闹钟提示
msg = f"闹钟时间到!" # 基本信息
if self.alarm_label: # 如果设置了标签
msg += f"\n{self.alarm_label}" # 添加标签信息
QMessageBox.information(self, "闹钟!", msg) # 显示闹钟提示
# 根据重复设置决定是否禁用闹钟
if self.alarm_repeat == "不重复": # 如果是不重复模式
self.alarm_enabled = False # 禁用闹钟
# 否则保持启用状态,以便明天再次触发
def start_explosion_animation(self): # 开始爆炸动画方法
# 创建动画组
self.explosion_animation_active = True # 设置爆炸动画为活跃状态
self.animation_group = QSequentialAnimationGroup(self) # 创建顺序动画组
# 第一部分:震动效果
shake_animation = QParallelAnimationGroup() # 创建并行动画组用于震动
# 创建8个随机方向的震动
for i in range(8): # 循环8次
pos_anim = QPropertyAnimation(self, b"pos") # 创建位置属性动画
pos_anim.setDuration(80) # 设置动画持续时间
pos_anim.setStartValue(self.pos()) # 设置起始位置
# 随机震动方向和距离
random_offset_x = random.randint(-15, 15) # 随机生成x偏移
random_offset_y = random.randint(-15, 15) # 随机生成y偏移
shake_pos = self.pos() + QPoint(random_offset_x, random_offset_y) # 计算震动位置
pos_anim.setEndValue(shake_pos) # 设置终点位置
pos_anim.setEasingCurve(QEasingCurve.OutInElastic) # 设置弹性缓动曲线
shake_animation.addAnimation(pos_anim) # 添加到震动动画组
# 如果不是最后一个震动,添加返回原位置的动画
if i < 7: # 除了最后一个
return_anim = QPropertyAnimation(self, b"pos") # 创建位置属性动画
return_anim.setDuration(80) # 设置动画持续时间
return_anim.setStartValue(shake_pos) # 设置起始位置
return_anim.setEndValue(self.pos()) # 设置终点位置
return_anim.setEasingCurve(QEasingCurve.OutInElastic) # 设置弹性缓动曲线
shake_animation.addAnimation(return_anim) # 添加到震动动画组
# 第二部分:爆炸效果(先放大后缩小)
explosion_animation = QSequentialAnimationGroup() # 创建顺序动画组用于爆炸
# 放大动画
expand_anim = QPropertyAnimation(self, b"size") # 创建大小属性动画
expand_anim.setDuration(200) # 设置动画持续时间
expand_anim.setStartValue(self.size()) # 设置起始大小
expand_anim.setEndValue(QSize(int(self.width() * 1.3), int(self.height() * 1.3))) # 设置终点大小
expand_anim.setEasingCurve(QEasingCurve.OutQuad) # 设置缓动曲线
# 缩小动画
shrink_anim = QPropertyAnimation(self, b"size") # 创建大小属性动画
shrink_anim.setDuration(200) # 设置动画持续时间
shrink_anim.setStartValue(QSize(int(self.width() * 1.3), int(self.height() * 1.3))) # 设置起始大小
shrink_anim.setEndValue(self.size()) # 设置终点大小
shrink_anim.setEasingCurve(QEasingCurve.InQuad) # 设置缓动曲线
# 添加到爆炸动画组
explosion_animation.addAnimation(expand_anim) # 添加放大动画
explosion_animation.addAnimation(shrink_anim) # 添加缩小动画
# 添加到主动画组
self.animation_group.addAnimation(shake_animation) # 添加震动动画
self.animation_group.addAnimation(explosion_animation) # 添加爆炸动画
# 设置动画结束时的回调
self.animation_group.finished.connect(self.on_explosion_animation_finished) # 连接完成信号到回调方法
# 开始动画
self.animation_group.start() # 启动动画组
def on_explosion_animation_finished(self): # 爆炸动画完成回调方法
# 动画结束,恢复正常状态
self.explosion_animation_active = False # 设置爆炸动画为非活跃状态
# 确保位置恢复正常
if self.original_position: # 如果有保存原始位置
self.move(self.original_position) # 移动到原始位置
def change_clock_style(self, style_index): # 切换表盘风格方法
self.clock_style = style_index # 更新风格索引
self.update() # 更新界面显示
def main(): # 主函数
app = QApplication(sys.argv) # 创建应用程序对象
clock = Clock() # 创建闹钟对象
clock.show() # 显示闹钟窗口
sys.exit(app.exec_()) # 运行应用程序事件循环并退出
if __name__ == '__main__': # 如果作为主程序运行
main() # 调用主函数
效果图