PyQt6实战2--Cron

cron表达式解析器和生成器

基本功能:

1.输入cron表达式,显示接下来的几条即将执行的时间 (测试下来只有5位是生效的)

2.选择规则生成cron

运行CronRunner即可:

运行效果展示

from PyQt6.QtWidgets import *
import sys
from cron import CronExpression
from generate_cron import GenerateCron

class CronRunner(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
        self.parseUI = CronExpression()
        self.generateUI = GenerateCron()

    def initUI(self):
        self.setWindowTitle('Cron 运行器')
        self.setGeometry(300, 300, 300, 200)

        layout = QVBoxLayout()

        parseBtn = QPushButton('解析 Cron 表达式')
        parseBtn.clicked.connect(self.parseCron)
        layout.addWidget(parseBtn)

        generateBtn = QPushButton('生成 Cron 表达式')
        generateBtn.clicked.connect(self.generateCron)
        layout.addWidget(generateBtn)

        self.setLayout(layout)



    def parseCron(self):
        self.generateUI.hide()
        self.parseUI.show()

    def generateCron(self):
        self.parseUI.hide()
        self.generateUI.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = CronRunner()
    demo.show()
    sys.exit(app.exec())


# cron表达式解析
# 这个croniter用起来感觉好多bug,不知道为啥 文档地址:https://github.com/kiorky/croniter
# 可能是我不会用,还是规则和正常的cron不一样,谁知道的可以评论一下

from PyQt6.QtWidgets import *
import sys
from croniter import croniter, CroniterBadCronError, CroniterNotAlphaError
from datetime import datetime

class CronExpression(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('Cron Expression Parser')
        self.setGeometry(300, 300, 500, 400)

        head = QGridLayout()
        self.input_label = QLabel('Cron 表达式:', self)
        self.input = QLineEdit()
        self.time_label = QLabel('时间:', self)
        self.time_input = QLineEdit()
        head.addWidget(self.input_label, 0, 0)
        head.addWidget(self.input, 0, 1)
        head.addWidget(self.time_label, 1, 0)
        head.addWidget(self.time_input, 1, 1)


        ops = QHBoxLayout()
        self.match_button = QPushButton('匹配', self)
        self.match_button.clicked.connect(self.matchCron)
        self.parse_button = QPushButton('查看最近即将执行的几条时间', self)
        self.parse_button.clicked.connect(self.parseCron)
        ops.addWidget(self.match_button)
        ops.addWidget(self.parse_button)
        self.output= QTextEdit()
        
        body = QVBoxLayout()
        body.addLayout(head)
        body.addLayout(ops)
        body.addWidget(self.output)

        self.setLayout(body)


    def parseCron(self):
        input_text = self.input.text()
        self.output.clear()
        
        try:
            cron = croniter(input_text, datetime.now())
            for i in range(5):
                next_time = cron.get_next(datetime)
                self.output.append(f"下一次执行时间: {next_time} \n")
        except CroniterNotAlphaError as e:
            self.output.setText("不兼容的表达式")
        except CroniterBadCronError as e:
            self.output.setText("表达式有问题")


    def matchCron(self):
        input_text = self.input.text()
        time_str = self.time_input.text()
        self.output.clear()
        try:
            time = datetime.strptime(time_str.strip(), '%Y-%m-%d %H:%M:%S')
            is_match = croniter.match(input_text, time)
            self.output.setText(f"时间 {time_str} 是否匹配: {is_match}")
        except ValueError as e:
            self.output.setText("时间格式错误")
        

    

if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = CronExpression()
    demo.show()
    sys.exit(app.exec())


    
from PyQt6.QtWidgets import *
from PyQt6.QtGui import *
from PyQt6.QtCore import *
import sys
from datetime import datetime



class GenerateCron(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()
        

    def initUI(self):
        self.setWindowTitle('Generate Cron')
        self.setGeometry(100, 100, 500, 400)
        self.setCentralWidget(QTextEdit())
        self.setWindowIcon(QIcon('../../img/json.png'))

        
        menuBar = self.menuBar()
        #这个方法必须调,否则在mac上出不来
        menuBar.setNativeMenuBar(False)

        s = QAction('秒', self)
        s.triggered.connect(self.showSecond)
        m = QAction('分钟', self)
        m.triggered.connect(self.showMinute)
        h = QAction('小时', self)
        h.triggered.connect(self.showHour)
        d = QAction('天', self)
        d.triggered.connect(self.showDay)
        mon = QAction('月', self)
        mon.triggered.connect(self.showMonth)
        menuBar.addAction(s)
        menuBar.addAction(m)
        menuBar.addAction(h)
        menuBar.addAction(d)
        menuBar.addAction(mon)

        self.parseLayout = QHBoxLayout()
        self.parseBtn = QPushButton('生成')
        self.parseBtn.clicked.connect(self.parse)
        self.parseRes = QLineEdit()
        self.parseLayout.addWidget(self.parseBtn)
        self.parseLayout.addWidget(self.parseRes)
        self.parseLayout.setAlignment(Qt.AlignmentFlag.AlignLeft)
        
        self.second = Second()
        self.minute = Minute()
        self.hour = Hour()
        self.day = Day()
        self.month = Month()
        self.stackWidget = QStackedWidget()
        self.stackWidget.addWidget(self.second)
        self.stackWidget.addWidget(self.minute)
        self.stackWidget.addWidget(self.hour)
        self.stackWidget.addWidget(self.day)
        self.stackWidget.addWidget(self.month)


        self.center = QWidget()
        self.centerLayout = QVBoxLayout()
        self.centerLayout.addWidget(self.stackWidget)
        self.centerLayout.addLayout(self.parseLayout)
        self.center.setLayout(self.centerLayout)

        self.setCentralWidget(self.center)



    def showSecond(self):
        self.stackWidget.setCurrentIndex(0)
    
    def showMinute(self):
        self.stackWidget.setCurrentIndex(1)

    def showHour(self):
        self.stackWidget.setCurrentIndex(2)

    def showDay(self):
        self.stackWidget.setCurrentIndex(3)

    def showMonth(self):
        self.stackWidget.setCurrentIndex(4)

    def parse(self):
        self.parseRes.setText(self.getCronExpression())


    def getCronExpression(self):
        s = self.second.getCron()
        m = self.minute.getCron()
        h = self.hour.getCron()
        d = self.day.getCron()
        m = self.month.getCron()
        return f"{s} {m} {h} {d} {m}" 


'''
定义cron展示的抽象类
样式来自:https://cron.qqe2.com/
'''
class AbstractCronUI(QWidget):
    def __init__(self):
        super().__init__()
        self.key = self.getKey()
        self.initUI()

    def getKey(self):
        pass
    
    def initUI(self):
        self.customize_checkbox = []
        self.setWindowTitle('cron表达式生成器')

        self.setGeometry(100, 100, 500, 300)
        layout = QVBoxLayout()

        perLayout = QHBoxLayout()
        self.per = QRadioButton()
        self.per.setChecked(True)
        perLabel = QLabel(f'每{self.key} 允许的通配符[, - * /]')
        perLayout.addWidget(self.per)
        perLayout.addWidget(perLabel)
        perLayout.setAlignment(Qt.AlignmentFlag.AlignLeft)

        periodLayout = QHBoxLayout()
        self.period = QRadioButton()
        periodLabel1 = QLabel('周期 从')
        self.periodInput1 = QLineEdit()
        periodLabel2 = QLabel('-')
        self.periodInput2 = QLineEdit()
        periodLabel3 = QLabel(f'{self.key}')
        periodLayout.addWidget(self.period)
        periodLayout.addWidget(periodLabel1)
        periodLayout.addWidget(self.periodInput1)
        periodLayout.addWidget(periodLabel2)
        periodLayout.addWidget(self.periodInput2)
        periodLayout.addWidget(periodLabel3)
        periodLayout.setAlignment(Qt.AlignmentFlag.AlignLeft)

        spanLayout = QHBoxLayout()
        self.span = QRadioButton()
        spanLabel1 = QLabel('从')
        self.spanInput1 = QLineEdit()
        spanLabel2 = QLabel(f'{self.key}开始,每')
        self.spanInput2 = QLineEdit()
        spanLabel3 = QLabel(f'{self.key}执行一次')
        spanLayout.addWidget(self.span)
        spanLayout.addWidget(spanLabel1)
        spanLayout.addWidget(self.spanInput1)
        spanLayout.addWidget(spanLabel2)
        spanLayout.addWidget(self.spanInput2)
        spanLayout.addWidget(spanLabel3)
        spanLayout.setAlignment(Qt.AlignmentFlag.AlignLeft)

        customizeLayout = QHBoxLayout()
        self.customizeBtn = QRadioButton()
        customizeLabel = QLabel('指定')
        customizeLayout.addWidget(self.customizeBtn)
        customizeLayout.addWidget(customizeLabel)
        customizeLayout.setAlignment(Qt.AlignmentFlag.AlignLeft)

        girdlayout = self.customize()

        layout.addLayout(perLayout)
        layout.addLayout(periodLayout)
        layout.addLayout(spanLayout)
        layout.addLayout(customizeLayout)
        layout.addLayout(girdlayout)
        self.setLayout(layout)

    def customize(self):
        pass

    def getCron(self):
        if(self.per.isChecked()):
            return "*"
        elif(self.period.isChecked()):
            pi1 = self.periodInput1.text()
            pi2 = self.periodInput2.text()
            return pi1 + "-" + pi2
        elif(self.span.isChecked()):
            si1 = self.spanInput1.text()
            si2 = self.spanInput2.text()
            return si1 + "/" + si2
        elif(self.customizeBtn.isChecked()):
            cron = ""
            for i in range(self.customize_checkbox.length):
                if(self.customize_checkbox[i].isChecked()):
                    cron += str(i) + ","
            return cron[:-1]
        return ""
    

class Second(AbstractCronUI):
    def __init__(self):
        super().__init__()
        

    def getKey(self):
        return "秒"

    def customize(self):
        self.girdlayout = QGridLayout()
        for i in range(60):
            c0 = QCheckBox()
            l0 = QLabel(str(i))
            self.girdlayout.addWidget(c0,i//10,i%10 * 2)
            self.girdlayout.addWidget(l0,i//10,i%10 * 2 + 1)

            self.customize_checkbox.append(c0)
        return self.girdlayout
    


class Minute(AbstractCronUI):
    def __init__(self):
        super().__init__()
        
    def getKey(self):
        return "分钟"

    def customize(self):
        girdlayout = QGridLayout()
        for i in range(60):
            c0 = QCheckBox()
            l0 = QLabel(str(i))
            girdlayout.addWidget(c0,i//10,i%10 * 2)
            girdlayout.addWidget(l0,i//10,i%10 * 2 + 1)
            self.customize_checkbox.append(c0)
        return girdlayout


class Hour(AbstractCronUI):
    def __init__(self):
        super().__init__()
    
    def getKey(self):
        return "小时"
    
    def customize(self):
        girdlayout = QGridLayout()
        for i in range(24):
            c0 = QCheckBox()
            l0 = QLabel(str(i))
            girdlayout.addWidget(c0,i//12,i%12 * 2)
            girdlayout.addWidget(l0,i//12,i%12 * 2 + 1)
            self.customize_checkbox.append(c0)
        return girdlayout
    


class Day(AbstractCronUI):
    def __init__(self):
        super().__init__()

    def getKey(self):
        return "日"

    def customize(self):
        girdlayout = QGridLayout()
        for i in range(31):
            c0 = QCheckBox()
            l0 = QLabel(str(i + 1))
            girdlayout.addWidget(c0,i//7,i%7 * 2)
            girdlayout.addWidget(l0,i//7,i%7 * 2 + 1)
            self.customize_checkbox.append(c0)
        return girdlayout


class Month(AbstractCronUI):
    def __init__(self):
        super().__init__()

    def getKey(self):
        return "月"
    
    def customize(self):
        girdlayout = QGridLayout()
        for i in range(12):
            c0 = QCheckBox()
            l0 = QLabel(str(i + 1))
            girdlayout.addWidget(c0,i//12,i%12 * 2)
            girdlayout.addWidget(l0,i//12,i%12 * 2 + 1)
        return girdlayout



if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = GenerateCron()
    demo.show()
    sys.exit(app.exec())

代码地址

GitHub - chunlaiqingke/Tiny-Tool

公众号

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值