州的先生因为干眼症的原因,电脑屏幕看久了,眼睛就会干涩和不适。所以除了靠「玻璃酸钠滴眼液」续命外,每隔那么一会儿,都得离开电脑屏幕,让眼睛休息一会儿。
大家写代码都知道的,一旦写得起劲,或是遇到一个问题,疯狂地在找解决方法,就会忘却了时间、忘却了休息。
等到回过神来,眼睛早已产生了不适感。
所以州的先生一直在使用腾讯电脑管家中的「休息助手」,每隔一段时间,电脑屏幕就会弹出让自己休息一会儿的弹出层。
最近州的先生换了一台电脑,但是又不想为了这么一个小小的工具而安装腾讯电脑管家,便在网上搜索有无类似的小工具。一通搜索,没有发现特别合适的工具。
转念一想,这个工具功能也不复杂,不如自己写一个吧。
经过构思和参考现有的软件,我们先从整体上来设计一下这个软件的结构。
首先,程序最主要得有一个倒计时的窗口,这个窗口是要占满整个屏幕的。用于实时显示休息的倒计时,并在倒计时结束之后关闭窗口。
然后,还有一个设置面板,用来配置程序的开关、休息周期等信息。
最后,要有一个程序托盘,用于退出和打开设置面板。
设计好之后,我们开始写代码。
首先,我们来创建这个倒计时面板。
定义一个继承自QtWidgets.QMainWindow
,名为Tips
的类:
# 提示框
class Tips(QtWidgets.QMainWindow):
def __init__(self,secound = 1000):
super(Tips, self).__init__()
在Tips中定义 4 个小部件,它们分别是:
# 倒计时文本
self.timer_lable = QtWidgets.QLabel("倒计时:00:00:00")
self.timer_lable.setAlignment(QtCore.Qt.AlignCenter)
self.timer_lable.setFont(QtGui.QFont('微软雅黑',30))
self.timer_lable.setStyleSheet('''
font-weight:900;
color:white;
''')
# 当前时间文本
self.datetime_label = QtWidgets.QLabel("2020-02-02 02:20:20")
self.datetime_label.setAlignment(QtCore.Qt.AlignCenter)
self.datetime_label.setStyleSheet('''
font-size:30px;
color:white;
font-weight:700;
font-family:sans-serif;
''')
# 提示文字
self.tall_text = QtWidgets.QLabel("眼睛累了,起身远眺,活动筋骨,休息一下吧")
self.tall_text.setFont(QtGui.QFont('微软雅黑',20))
self.tall_text.setAlignment(QtCore.Qt.AlignCenter)
self.tall_text.setStyleSheet('''
color:white;
font-weight:700;
''')
# 退出按钮
self.quit_btn = QtWidgets.QPushButton("结束休息")
self.quit_btn.setFont(QtGui.QFont('微软雅黑',20))
self.quit_btn.clicked.connect(self.stop_rest)
self.quit_btn.setStyleSheet('''
background-color:#f44545;
color:white;
''')
用一个网格布局层来对上述 4 个小部件进行布局:
self.main_layout = QtWidgets.QGridLayout()
self.main_layout.addWidget(self.timer_lable,0,0)
self.main_layout.addWidget(self.tall_text, 1, 0)
self.main_layout.addWidget(self.datetime_label,2,0)
self.main_layout.addWidget(self.quit_btn,3,0)
接着对窗口进行处理:
self.main_widget = QtWidgets.QWidget()
self.main_widget.setLayout(self.main_layout)
self.setCentralWidget(self.main_widget)
self.setWindowOpacity(1) # 设置窗口透明度
# self.setAttribute(QtCore.Qt.WA_TranslucentBackground) # 设置窗口背景透明
self.setWindowFlag(QtCore.Qt.FramelessWindowHint) # 隐藏边框
self.setStyleSheet('''
background-color:#333;
''')
我们来显示一下这个图形:
def main():
app = QtWidgets.QApplication(sys.argv)
QtWidgets.QApplication.setQuitOnLastWindowClosed(False)
gui = Tips()
gui.showFullScreen()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
窗口如下图所示:
然后用两个计时器来实时更新当前时间和倒计时:
# 实时时间计时器
self.datetime = QtCore.QTimer() # 实例化一个计时器
self.datetime.setInterval(1000) # 设置计时器间隔1秒
self.datetime.start() # 启动计时器
self.datetime.timeout.connect(self.show_datetime_slots) # 计时器连接到槽函数更新UI界面时间
# 倒计时计时器
self.timer_time = QtCore.QTimer() # 实例化一个计时器
self.timer_time.setInterval(1000)
# self.timer_time.start()
self.timer_time.timeout.connect(self.show_timer_slots)
这样,我们的倒计时面板基本上就完成了。
设置面板的作用在于控制倒计时面板。比如:
在上述功能中,状态我们使用QRadioButton
单选按钮组件来实现,休息周期使用QComboBox
下拉框组件来实现,休息时间使用QLineEdit
输入框组件来实现,最后通过一个网格布局QGridLayout
将其整合在一起,最终代码为:
# 设置面板
class MainPanel(QtWidgets.QWidget):
def __init__(self):
super(MainPanel, self).__init__()
self.setWindowTitle("电脑休息助手 v0.1 - 州的先生")
self.setWindowIcon(QtGui.QIcon("./icon.png"))
self.cycle_list = ['1','20','30','40','50','60']
self.tips_cycle_secound = 1000 # 间隔秒数
self.tips_rest_secound = 1000 # 休息秒数
self.tips_status = False # 状态
# 控制开关
self.switch_label = QtWidgets.QLabel("状态:")
self.switch_radio_en = QtWidgets.QRadioButton("开启")
self.switch_radio_dis = QtWidgets.QRadioButton("关闭")
# 休息周期
self.rest_label = QtWidgets.QLabel("休息周期:")
self.rest_txt_1 = QtWidgets.QLabel("每")
self.rest_cycle_input = QtWidgets.QComboBox()
self.rest_cycle_input.addItems(self.cycle_list)
self.rest_txt_2 = QtWidgets.QLabel("分钟,休息")
self.rest_time_input = QtWidgets.QLineEdit()
self.rest_time_input.setValidator(QtGui.QIntValidator(1,999))
self.rest_txt_3 = QtWidgets.QLabel("分钟")
# 距离下一轮休息文本
self.next_label = QtWidgets.QLabel("下次休息:")
self.next_time_label = QtWidgets.QLabel("")
# 保存
self.save_btn = QtWidgets.QPushButton("保存")
self.save_btn.clicked.connect(self.save_config)
# 添加到布局层
self.main_layout = QtWidgets.QGridLayout()
## 启用状态
self.main_layout.addWidget(self.switch_label,0,0,1,1)
self.main_layout.addWidget(self.switch_radio_en, 0, 1, 1, 1)
self.main_layout.addWidget(self.switch_radio_dis, 0, 2, 1, 1)
# 运行周期
self.main_layout.addWidget(self.rest_label,1,0,1,1)
self.main_layout.addWidget(self.rest_txt_1, 1, 1, 1, 1)
self.main_layout.addWidget(self.rest_cycle_input, 1, 2, 1, 1)
self.main_layout.addWidget(self.rest_txt_2, 1, 3, 1, 1)
self.main_layout.addWidget(self.rest_time_input, 1, 4, 1, 1)
self.main_layout.addWidget(self.rest_txt_3, 1, 5, 1, 1)
# 下次休息倒计时
self.main_layout.addWidget(self.next_label, 2, 0, 1, 1)
self.main_layout.addWidget(self.next_time_label, 2, 1, 1, 1)
# 保存
self.main_layout.addWidget(self.save_btn, 3, 0, 1, 1)
self.setLayout(self.main_layout)
上述代码将会显示如下图所示的窗口:
作为一个小巧的工具,它一定是不能太扰乱我们的桌面的,所以托盘程序必不可少。
我们对程序的托盘设置两个功能:打开设置面板和退出程序
# 托盘配置
def tray_config(self):
self.openAction = QtWidgets.QAction("打开", self)
self.openAction.triggered.connect(self.showNormal)
self.quitAction = QtWidgets.QAction("退出", self)
self.quitAction.triggered.connect(self.quit)
self.trayIconMenu = QtWidgets.QMenu(self)
self.trayIconMenu.addAction(self.openAction)
self.trayIconMenu.addAction(self.quitAction)
self.trayIcon = QtWidgets.QSystemTrayIcon(self)
self.trayIcon.setContextMenu(self.trayIconMenu)
self.trayIcon.setIcon(QtGui.QIcon("./icon.png"))
self.trayIcon.setToolTip("休息助手")
self.trayIcon.show()
上述代码将会把让我们得到如下图所示的托盘:
程序的打包可以使用 PyInstaller 或 Nuitka。
比较简单的是使用 PyInstaller:
pyinstaller -w main.py
即可打包为一个文件夹类型的程序包,在这里我们不推荐将其打包为一个单文件的二进制程序包。
这样一个小巧的工具,当然还有不断迭代的空间和余地,所以州的先生将其开源在了 Gitee 平台,希望大家群策群力,一起维护好这个小工具。
仓库地址为:https://gitee.com/zmister/rest-helper