本项目是Python&PySide6构建的番茄钟软件,这是我的第一个独立项目。
总览
在学习完Python的入门和进阶教程后,我认为我需要用项目来巩固已学内容,制作实用软件能够有效的提高我的编程能力。
在开始项目前,我构建了该项目的思维导图,打算以此分步骤实现各功能,思维导图如下:
软件运行时界面如下:
当前版本未实现功能
- 读写配置文件
- 休息时长自定义
- 显示番茄次数
开发过程时的反馈
第一版完成反馈:
实现了最基础的定时功能,但是使用的是sleep指令,在这期间程序没办法进行其他操作,同时需要实现时间倒计时、多线程、界面、配置文件储存等功能。现在开始学习PyQt实现图形化界面。
第二版完成反馈:
基本完成了番茄钟核心功能,实现了多线程执行倒计时,Qt实现GUI,基本逻辑漏洞都已修补完毕。待添加功能:界面美化、设置界面、配置文件储存、记录番茄次数、小憩休息功能。
项目依赖
Python 3.7+
Pyside6(pip install pyside6)
Qt material(pip install qt_material)
Playsound(pip install playsound)
我的想法
这是我第一次独立编写项目,代码可能不是那么好,在处理线程时还遇到了不知道怎么停止线程的情况,搜索了几次之后,我发现给线程添加一个标识符并在循环流程中一直判断,是比较有效的办法。
我是一个新手,代码的编写规范也都是从论坛里东拼西凑学习的,还希望各位能给我一些指导或者建议!
完整版的源代码在Hub上搜索Pomorodo-timer-GUI就可以找到了,有音频资源和UI布局资源。
源代码
from PySide6.QtWidgets import QApplication
from PySide6.QtUiTools import QUiLoader
from PySide6.QtGui import QIcon
from qt_material import apply_stylesheet
from time import sleep
from threading import Thread
from playsound import playsound
from settings import TSettings
class Tomato():
m_focustime = 0
m_resttime = 5
status_flag = False
ts = TSettings()
def __init__(self):
self.BindEvents()
def BindEvents(self):
self.window = QUiLoader().load(self.ts.dir_ui)
self.window.setFixedSize(self.window.width(),self.window.height())
self.window.start.clicked.connect(self.StartFocus)
self.window.reset.clicked.connect(self.ResetTime)
self.window.reset.setProperty('class','warning')
self.window.timedial.valueChanged.connect(self.SetTime)
def ClockThread(self):
while self.status_flag == True:
self.isZero()
for i in range(self.m_focustime):
if self.status_flag:
sleep(60) #休眠时长
self.CountDown()
else:
pass
def isZero(self):
if self.window.timedial.value() == 0:
self.status_flag = False
self.window.start.setText(self.ts.button_text[1])
self.StopFocus()
def CountDown(self):
if self.window.timedial.value() >= 0 and self.window.timedial.value() < 10:
self.window.timelabel.setText(self.ts.time[1].format(int(self.window.timelabel.text()[-1]) - 1))
self.window.timedial.setValue(self.window.timedial.value() - 1)
elif self.window.timedial.value() < 60:
self.window.timelabel.setText(self.ts.time[2].format(int(self.window.timelabel.text()[-2:]) - 1))
self.window.timedial.setValue(self.window.timedial.value() - 1)
elif self.window.timedial.value() == 60:
self.window.timelabel.setText(self.ts.time[4])
self.window.timelabel.setText(self.ts.time[2].format(int(self.window.timelabel.text()[-2:]) - 1))
self.window.timedial.setValue(self.window.timedial.value() - 1)
def StartFocus(self):
if self.status_flag == False:
self.status_flag = True
self.window.start.setText(self.ts.button_text[0])
thread_clock = Thread(target = self.ClockThread)
thread_clock.start()
else:
self.StopThread()
self.window.start.setText(self.ts.button_text[1])
self.isZero()
def StopFocus(self):
thread_music = Thread(target=self.Music)
thread_music.start()
def StopThread(self):
self.status_flag = False
def ResetTime(self):
self.StopThread()
self.window.timedial.setValue(0)
self.window.timelabel.setText(self.ts.time[0])
def SetTime(self):
if self.window.timedial.value() < 10:
self.window.timelabel.setText(self.ts.time[1].format(self.window.timedial.value()))
self.m_focustime = self.window.timedial.value()
elif self.window.timedial.value() <60:
self.window.timelabel.setText(self.ts.time[2].format(self.window.timedial.value()))
self.m_focustime = self.window.timedial.value()
elif self.window.timedial.value() == 60:
self.window.timelabel.setText(self.ts.time[3])
self.m_focustime = self.window.timedial.value()
def Music(self):
playsound(self.ts.dir_music)
def main():
app = QApplication([])
app.setWindowIcon(QIcon('./ui/logo.png'))
tomato = Tomato()
ts = TSettings()
apply_stylesheet(app,
theme=ts.theme,invert_secondary=False,
extra=ts.style_extra)
tomato.window.show()
app.exec()
if __name__ == '__main__':
main()