【开源工具】基于PyQt5工作时长计算器工具开发全解析 - 教程

news/2025/10/7 14:08:59/文章来源:https://www.cnblogs.com/wzzkaifa/p/19128453

PyQt5实用小工具:工作时长计算器工具开发全解析

在这里插入图片描述
请添加图片描述

? 个人主页:创客白泽 - CSDN博客
? 系列专栏:?《Python开源项目实战》
? 热爱不止于代码,热情源自每一个灵感闪现的夜晚。愿以开源之火,点亮前行之路。
? 如果觉得这篇文章有帮助,欢迎您一键三连,分享给更多人哦

请添加图片描述
在这里插入图片描述


摘要:
在日常工作和项目管理中,准确计算工作时长是非常重要的。本文将深入讲解如何利用PyQt5开发一个简单易用的“工作时长计算器”桌面应用,涵盖设计思路、功能实现、UI布局、核心代码解析及打包细节。文中配有示例代码和界面截图,帮助读者快速掌握PyQt5实战技能。


目录


概述

随着远程办公和弹性工作制的兴起,个人及团队对于工作时长的准确统计需求日益增长。虽然市面上有众多复杂的考勤软件,但对于简单的时间计算需求,一个轻量级且界面友好的桌面应用更具实用性和便利性。

本文介绍的“工作时长计算器”基于Python的PyQt5库开发,体积小巧,界面简洁,支持用户输入上下班时间,一键计算出当天工作时长,并可将结果复制到剪贴板,方便粘贴到日报、考勤系统或聊天工具中。


功能介绍


界面展示

1. 主界面

在这里插入图片描述

图1:工作时长计算器主界面,简洁明了,支持键盘输入与按钮操作

2. 计算结果显示与复制反馈

在这里插入图片描述

图2:计算完成后显示时长,点击复制按钮弹出提示


软件使用步骤说明

  1. 启动程序:运行python work_time_calculator.py
  2. 输入上班时间:如08:30
  3. 输入下班时间:如17:45
  4. 点击“计算工作时长”按钮,显示工作时长,例如08:15
  5. 点击“复制时长”按钮,将结果复制到剪贴板,方便粘贴
  6. 勾选“窗口置顶”,保持程序界面在最前端
  7. 如输入格式错误,弹出错误提示框,请按提示修改时间格式

代码详解

窗口初始化与布局

class WorkTimeCalculator(QWidget):
def __init__(self):
super(
).__init__(
)
self.setWindowTitle("工作时长计算器"
)
self.setFixedSize(320
, 380
)
# 设置窗口图标
icon_path = self.resource_path("time.ico"
)
self.setWindowIcon(QIcon(icon_path)
)
# 窗口置顶属性
self.setWindowFlags(self.windowFlags(
) | Qt.WindowStaysOnTopHint)
self.duration_str = ""
self.init_ui(
)
  • QWidget是PyQt中最基础的窗口类。
  • 固定窗口大小,保证UI布局一致性。
  • 使用自定义图标美化程序。
  • 通过Qt.WindowStaysOnTopHint保持窗口置顶。

UI组件布局采用QVBoxLayout垂直堆叠控件,样式使用QFontsetStyleSheet增强视觉体验。


工作时长计算核心逻辑

def calculate_time(self):
start_text = self.input_start.text(
).strip(
)
end_text = self.input_end.text(
).strip(
)
try:
start_time = datetime.strptime(start_text, "%H:%M"
)
end_time = datetime.strptime(end_text, "%H:%M"
)
if end_time < start_time:
end_time = end_time.replace(day=start_time.day + 1
)
duration = end_time - start_time
total_minutes = duration.seconds // 60
hours = total_minutes // 60
minutes = total_minutes % 60
self.duration_str = f"{
hours:02
}:{
minutes:02
}"
self.result_label.setText(f"? 工作时长:{
self.duration_str
}"
)
except ValueError:
QMessageBox.warning(self, "❌ 错误"
, "请输入有效时间格式,如 09:00"
)
  • 使用datetime.strptime解析输入时间。
  • 处理跨天工作(如夜班,结束时间小于开始时间时,自动视为第二天)。
  • 计算时间差,转换成小时和分钟。
  • 结果格式化为HH:MM,更新界面标签显示。
  • 异常处理避免程序崩溃,弹出错误提示框。

剪贴板复制与状态提示

def copy_duration(self):
if self.duration_str:
QApplication.clipboard(
).setText(self.duration_str)
self.show_status_message(f"⏱️ 时长 {
self.duration_str
} 已复制到剪贴板"
, 1200
)
else:
QMessageBox.warning(self, "⚠️ 无数据"
, "请先计算工作时长"
)
def show_status_message(self, message, timeout=1000
):
self.status_label.setText(message)
self.status_label.setVisible(True
)
QTimer.singleShot(timeout,
lambda: self.status_label.setVisible(False
)
)
  • 复制时长字符串到系统剪贴板。
  • 使用状态栏显示短暂提示,提升用户交互体验。
  • 未计算前复制操作给出警告提示。

窗口置顶功能

def toggle_topmost(self, state):
if state == Qt.Checked:
self.setWindowFlags(self.windowFlags(
) | Qt.WindowStaysOnTopHint)
else:
self.setWindowFlags(self.windowFlags(
) &
~Qt.WindowStaysOnTopHint)
self.show(
)
  • 通过QCheckBox切换窗口置顶属性。
  • 动态刷新窗口状态,确保设置生效。

源码下载

import sys
import os
from PyQt5.QtWidgets import (
QApplication, QWidget, QLabel, QLineEdit, QPushButton,
QVBoxLayout, QMessageBox, QCheckBox
)
from PyQt5.QtGui import QFont, QIcon
from PyQt5.QtCore import Qt, QTimer
from datetime import datetime
class WorkTimeCalculator(QWidget):
def __init__(self):
super(
).__init__(
)
self.setWindowTitle("工作时长计算器"
)
self.setFixedSize(320
, 380
)
# 设置窗口图标
icon_path = self.resource_path("time.ico"
)
self.setWindowIcon(QIcon(icon_path)
)
self.setWindowFlags(self.windowFlags(
) | Qt.WindowStaysOnTopHint)
self.duration_str = ""
self.init_ui(
)
def init_ui(self):
font = QFont("Arial"
, 12
)
self.label_start = QLabel("?‍? 上班时间 (HH:MM):"
)
self.label_start.setFont(font)
self.input_start = QLineEdit(
)
self.input_start.setPlaceholderText("如:08:30"
)
self.input_start.setFont(font)
self.input_start.setStyleSheet("""
QLineEdit {
border: 2px solid #ccc;
border-radius: 10px;
padding: 6px 10px;
}
"""
)
self.label_end = QLabel("? 下班时间 (HH:MM):"
)
self.label_end.setFont(font)
self.input_end = QLineEdit(
)
self.input_end.setPlaceholderText("如:17:45"
)
self.input_end.setFont(font)
self.input_end.setStyleSheet("""
QLineEdit {
border: 2px solid #ccc;
border-radius: 10px;
padding: 6px 10px;
}
"""
)
self.button_calc = QPushButton("✅ 计算工作时长"
)
self.button_calc.setFont(font)
self.button_calc.setStyleSheet("""
QPushButton {
background-color: #4CAF50;
color: white;
border: none;
border-radius: 10px;
padding: 8px;
}
QPushButton:hover {
background-color: #45a049;
}
QPushButton:pressed {
background-color: #3e8e41;
}
"""
)
self.button_calc.clicked.connect(self.calculate_time)
self.result_label = QLabel("? 工作时长:--:--"
)
self.result_label.setFont(QFont("Arial"
, 13
, QFont.Bold)
)
self.copy_button = QPushButton("? 复制时长"
)
self.copy_button.setFont(font)
self.copy_button.setStyleSheet("""
QPushButton {
background-color: #2196F3;
color: white;
border: none;
border-radius: 10px;
padding: 8px;
}
QPushButton:hover {
background-color: #1e88e5;
}
QPushButton:pressed {
background-color: #1976d2;
}
"""
)
self.copy_button.clicked.connect(self.copy_duration)
self.checkbox_topmost = QCheckBox("? 窗口置顶"
)
self.checkbox_topmost.setFont(font)
self.checkbox_topmost.setChecked(True
)
self.checkbox_topmost.stateChanged.connect(self.toggle_topmost)
self.status_label = QLabel(""
)
self.status_label.setFont(QFont("Arial"
, 10
)
)
self.status_label.setStyleSheet("color: white; background-color: #444; padding: 4px; border-radius: 4px;"
)
self.status_label.setAlignment(Qt.AlignCenter)
self.status_label.setVisible(False
)
layout = QVBoxLayout(
)
layout.setSpacing(8
)
layout.setContentsMargins(16
, 16
, 16
, 16
)
layout.addWidget(self.label_start)
layout.addWidget(self.input_start)
layout.addWidget(self.label_end)
layout.addWidget(self.input_end)
layout.addWidget(self.button_calc)
layout.addWidget(self.result_label)
layout.addWidget(self.copy_button)
layout.addWidget(self.checkbox_topmost)
layout.addWidget(self.status_label)
self.setLayout(layout)
def calculate_time(self):
start_text = self.input_start.text(
).strip(
)
end_text = self.input_end.text(
).strip(
)
try:
start_time = datetime.strptime(start_text, "%H:%M"
)
end_time = datetime.strptime(end_text, "%H:%M"
)
if end_time < start_time:
end_time = end_time.replace(day=start_time.day + 1
)
duration = end_time - start_time
total_minutes = duration.seconds // 60
hours = total_minutes // 60
minutes = total_minutes % 60
self.duration_str = f"{
hours:02
}:{
minutes:02
}"
self.result_label.setText(f"? 工作时长:{
self.duration_str
}"
)
except ValueError:
QMessageBox.warning(self, "❌ 错误"
, "请输入有效时间格式,如 09:00"
)
def copy_duration(self):
if self.duration_str:
QApplication.clipboard(
).setText(self.duration_str)
self.show_status_message(f"⏱️ 时长 {
self.duration_str
} 已复制到剪贴板"
, 1200
)
else:
QMessageBox.warning(self, "⚠️ 无数据"
, "请先计算工作时长"
)
def show_status_message(self, message, timeout=1000
):
self.status_label.setText(message)
self.status_label.setVisible(True
)
QTimer.singleShot(timeout,
lambda: self.status_label.setVisible(False
)
)
def toggle_topmost(self, state):
if state == Qt.Checked:
self.setWindowFlags(self.windowFlags(
) | Qt.WindowStaysOnTopHint)
else:
self.setWindowFlags(self.windowFlags(
) &
~Qt.WindowStaysOnTopHint)
self.show(
)
def resource_path(self, relative_path):
"""解决打包后资源路径问题"""
if hasattr(sys, '_MEIPASS'
):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath("."
)
, relative_path)
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setStyle("Fusion"
)
window = WorkTimeCalculator(
)
window.show(
)
sys.exit(app.exec_(
)
)

总结与展望

本文详细介绍了基于PyQt5的“工作时长计算器”的开发过程,涵盖了窗口设计、时间处理逻辑、交互细节及用户体验优化。该工具简单实用,适合日常办公人员快速统计工作时长。

未来可以拓展的功能有:

欢迎大家试用源码,提出宝贵意见,共同完善!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/930487.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

十六、【前端强化篇】完善 TestCase 编辑器:支持 API 结构化定义与断言安装

十六、【前端强化篇】完善 TestCase 编辑器:支持 API 结构化定义与断言安装2025-10-07 14:04 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x…

斑马ZT210碳带及纸张安装教程

1、碳带安装方法说明图:2、纸张安装说明图:3、综合图:4、实物图:

石家庄网站搭建定制vi设计获奖作品

一.概述 1.1 以太网指的是由Xerox公司创建并由Xerox、Intel和DEC公司联合开发的基带总线局域网规范&#xff0c;是当今现有局域网采用的最通用的通信协议标准。以太网络使用CSMA/CD技术。 1.2 以太网在局域网各种技术中占统治性地位。 造价低;是应用最广泛的局域网技术。比令…

DHCP及DNS

dhcp enable //开启dncp ip pool xxx //创建一个叫xxx的地址池 network xxx.xxx mask yyy.yyy//设置地址池的相关参数 gateway-list zzz.zzz//设置地址池的网关 dns-list ddd.ddd//设置地址池的DNS huawei路由器还…

Gitlab Runner 学习

Gitlab Runner 学习 runner下载|安装|启动 下载 # 为您的系统下载二进制文件 sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runne…

代做备案网站专业郑州企业网站建设

文章目录 1. 简介2. 用法1&#xff09;单个 CommandLineRunner2&#xff09;多个 CommandLineRunner 3. 优点4. 缺点总结 CommandLineRunner 是 Spring Boot 提供的一个接口&#xff0c;用于在 Spring Boot 应用程序启动后执行一些任务。通过实现 CommandLineRunner 接口&#…

东莞网站建设设计公司网站怎么添加域名

Redisson 中的 RScoredSortedSet 类是对 Redis 内置的 Sorted Set 数据结构的一个封装&#xff0c;它支持对集合中的元素进行排序&#xff0c;每个元素都有一个与之关联的分数(score)。 RScoredSortedSet 可以用于多种场景&#xff0c;以下是一些常见的使用案例&#xff1a; 排…

AI元人文:论价值原语博弈与人文知识库共建如何重塑智能社会的决策基石

AI元人文:论价值原语博弈与人文知识库共建如何重塑智能社会的决策基石 我们这个时代面临着深刻的人文困境。表面上是技术冲击与规则失能,实则是规则逻辑与人文逻辑的断裂。规则逻辑构筑现代社会的效率骨架,人文逻辑…

佳木斯网站建设网站建设报价明细表

【Matlab】智能优化算法_麻雀搜索算法SSA 1.背景介绍2.数学模型3.文件结构4.伪代码5.详细代码及注释5.1 Get_Functions_details.m5.2 main.m5.3 SSA.m 6.运行结果7.参考文献 1.背景介绍 麻雀通常是群居的鸟类&#xff0c;有很多种类。它们分布在世界的大部分地区&#xff0c;喜…

算法第一张作业

一、代码规范 对于大学生来说,不需要一开始就追求大公司那样面面俱到的规范,但也要抓住以下几个核心要点:命名规范,这是最重要、也是最容易见效的一条。 (1)变量/函数名:使用有意义的英文单词,不要用拼音或a, …

怎么使自己的网站秦淮做网站价格

六西格玛&#xff0c;这个在业界久负盛名的管理理念&#xff0c;它的魅力太强大了。曾听闻它能帮助企业和个人提升竞争力&#xff0c;但当真正走进这个培训体系时&#xff0c;会发现它的影响力远超你的想象。 在六西格玛的指导下&#xff0c;企业实现了显著的转变。之前那些看…

MySQL CentOS7 本地安装

假设已经删除了MySQL,如果你没有删除可以搜索一下 mysql-libs.zip 百度网盘 我这里是使用了unzip来解压 sudo yum install -y unzip zip unzip mysql-libs.zip cd mysql-libs 本来是使用rpm,但是这里缺少perl error:…

TypeScript装饰器 - Ref

TypeScript装饰器 01-简介02-类装饰器03-装饰器工厂04-装饰器组合05-属性装饰器06-方法装饰器07-访问器装饰器08-参数装饰器

网站服务器租用多少钱才合理呢什么是关键词

经过3个多小时的努力&#xff0c;配置JNDI数据源(主要是通过DBCP连接池)终于搞定&#xff5e;还是Tomcat官方的说明好&#xff0c;不过全是英文的&#xff0c;大概还看得懂&#xff0e;百度上那么花花绿绿的太多了&#xff0c;一个也没成功&#xff01;&#xff0e;&#xff0e…

【笔记】排列与组合学习笔记

前言 总概 本文章将会向你讲解排列与组合的基本知识和综合运用。 会从定义、问题导入、解决方法、经典例题、总结等方面讲解。 前置知识有一定的数学思维能力和理解能力 加法计数原理 乘法计数原理 阶乘加法计数原理和…

【高级数据结构】ST 表

前言 大部分 ST 表能解决的问题树状数组和线段树都能解决,只不过 ST 表的代码实现更加简单。 ST 表可以求解区间 $[l,r]$ 的最值问题等区间查询。 ST表 ST 表的定义 ST 表是利用倍增思想来解决区间问题的,这样可以缩…

【高级算法】树形DP

前言 本篇文章针对对于树形DP有一定基础的人,没学过的话请出门左转~ 树上背包 P1273 有线电视网 题目简述 有一棵有根树,每个叶子节点都有一个可赚的钱数,每走一条路都有相应的花费。 则在不亏本的情况下从根节点能…

如何提升网站seo排名h5都用什么网站

在日常的数据存储与管理中&#xff0c;移动硬盘作为便携且容量可观的存储设备&#xff0c;深受用户青睐。然而&#xff0c;当您发现联想闪电鲨移动硬盘中的文件突然消失&#xff0c;而您确信并未进行删除操作时&#xff0c;这无疑会令人感到困惑与焦虑。本文旨在为您揭开这一谜…

【高级数据结构】浅谈最短路

前言 最短路是图论中非常典型的模板之一,在生活中也可以到处见到许多。 例如在中国有许多个城市,我现在正在成都,现在我想开车去重庆,而在成都去往重庆的道路上,有许多的道路可以到达,而我想要以最快的速度到达,…

代码随想录打卡|Day53 图论(Floyd 算法精讲 、A * 算法精讲 (A star算法)、最短路算法总结篇、图论总结 ) - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …