如何以QDateTimeEdit显示格式指定一年中的某一天?

问题描述 投票:0回答:1

如何在 QDateTimeEdit 显示格式中使用一年中的某一天?我知道我可以使用 displayFormat 方法指定显示格式,但是 documentation 没有显示使用年中日期格式的方法。前任。 2023 年 7 月 29 日将是 2023-210。

我使用的所有数据都使用序号日期来跟踪信息。因此,最简单的方法是输入序数日期,而不是转换它然后输入它。

我当前的解决方案使用带有输入掩码和验证器方法的行编辑,但我想知道是否有更强大的解决方案。

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys

class DateEdit(QLineEdit):
    def __init__(self):
        super().__init__()
        self.textChanged.connect(self.validate)
        self.setPlaceholderText('yyyy-ddd')
    
    def validate(self):
        print(self.cursorPosition())
        text = self.text()
        print(text.split('-'))
        if len(text) > 5 and int(text.split('-')[1]) > 366:
            self.setText(text[:-1])
                
    def focusInEvent(self, event):
        if self.text() == '':
            self.setInputMask('9999-900')
    
    def focusOutEvent(self, event):
        if self.text() == '-':
            self.setInputMask('')

if __name__ == "__main__":
    app = QApplication(sys.argv)
    main = QWidget()
    main.setFixedSize(200, 100)
    edit1 = DateEdit()
    edit2 = DateEdit()
    layout = QHBoxLayout()
    layout.addWidget(edit1)
    layout.addWidget(edit2)
    main.setLayout(layout)
    main.show()
    app.exec()
qt pyqt
1个回答
0
投票

我修改了当前的 QDateEdit 以具有不同的显示和输入文本行为,同时仍然保留 QDateEdit 的功能(例如弹出菜单和上下文菜单)。当前的日期格式现在采用序数日期的形式(例如

2020/123
)。

为了实现这一点,我查看了Qt源代码和Qt文档,经过一番尝试和错误,我发现需要重新实现以下功能:

  • dateTimeFromText(text)
    [1]:用于解析序数日期格式的输入。
  • textFromDateTime(dt)
    [2]:用于以正确的格式显示序数日期。
  • validate(text, pos)
    [3]:根据序数日期格式更改验证。
  • stepBy(steps)
    [4] 和
    stepEnabled()
    [5]:这两个函数也被重新实现,以修复使用箭头键修改日期时的限制。

代码在我的测试中似乎工作正常,但可能存在一些错误。我也没有测试它的区域设置更改,但它应该提供一个很好的起点。 另外,我并不是真正的 Python 程序员,因此代码可能不符合最佳实践。

import sys
from PyQt5.QtGui import QValidator
from PyQt5.QtCore import QDate, QDateTime
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget, QDateEdit

class CustomDateEdit(QDateEdit):
    def __init__(self):
        super().__init__()
        self.setDisplayFormat('yyyy/dd')

    def dateTimeFromText(self, text):
        try:
            year_str, day_str = text.split('/')
            year, day = int(year_str), int(day_str)
        except:
            year, day = 1, 1

        date = QDateTime(QDate(year, 1, 1).addDays(day - 1))
        date.setTime(self.time())

        return QDateTime(date)

    def textFromDateTime(self, dt):
        year = dt.date().year()
        day = dt.date().dayOfYear()
        res = "{0}/{1:0>2}".format(year, day)
        return res

    def stepBy(self, steps):
        if self.currentSection() == QDateEdit.Section.DaySection:
            date = self.date()
            leap = QDate().isLeapYear(date.year())
            if date.dayOfYear() + steps <= (364 + int(leap)):
                self.setDate(date.addDays(steps))
        else:
            super().stepBy(steps)

    def stepEnabled(self):
        if self.currentSection() == QDateEdit.Section.DaySection:
            date = self.date()
            leap = QDate().isLeapYear(date.year())
            flag = QDateEdit.StepEnabledFlag.StepNone

            if date.dayOfYear() < (364 + int(leap)):
                flag = QDateEdit.StepEnabledFlag.StepUpEnabled
            if 1 < date.dayOfYear():
                flag |= QDateEdit.StepEnabledFlag.StepDownEnabled

            return flag
        else:
            return super().stepEnabled()

    def validate(self, text, pos):
        try:
            year_str, day_str = text.split('/')
            year, day = int(year_str), int(day_str)
        except:
            year, day = 1, 1

        new_date = QDate(year, 1, 1).addDays(day - 1)
        is_leap = new_date.isLeapYear(year)

        have_slash = text.count('/') == 1
        day_in_range = day < (364 + int(is_leap))
        range_valid = self.minimumDate() < new_date and new_date < self.maximumDate()

        if have_slash and day_in_range and range_valid:
            state = QValidator.Acceptable
        elif have_slash and year_str and len(year_str) < 4:
            state = QValidator.Intermediate
        else:
            state = QValidator.Invalid

        return (state, text, pos)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    main = QWidget()
    cdate_edit = CustomDateEdit()
    cdate_edit.setCalendarPopup(True)
    layout = QVBoxLayout()
    layout.addWidget(cdate_edit)
    main.setLayout(layout)
    main.show()
    sys.exit(app.exec())
© www.soinside.com 2019 - 2024. All rights reserved.