写点什么

PyQt5 实现可空值的 QDateTimeEdit

用户头像
一代咩神
关注
发布于: 2021 年 05 月 13 日

QDateTimeEdit 默认不允许为空,也就是不能存放空串 。网上搜寻了很久始终没找到答案,自行研究下,发现重写两个方法可以实现可空值的 QDateTimeEdit


def validate(self, input: str, pos: int) -> Tuple[QValidator.State, str, int]  """  判断 QDateTimeEdit 的输入是否有效,无效则不会输入到 QDateTimeEdit 中。    返回值 QValidator.State 有三种状态:    QValidator.Acceptable:允许;    QValidator.Intermediate:无法确定(即中间值);    QValidator.Invalid:拒绝。  str: 返回输入框应该显示的文本(非最终文本),默认为 input;  int: 返回输入框光标偏移量,默认为 pos。  """
def textFromDateTime(self, dateTime: QDateTime) -> str """每当要显示 dateTime 时会调用此函数,返回最终被显示在输入框中的内容。"""
复制代码


知道这两个方法的作用后开始一顿骚操作:


class DateTimeEdit(QDateTimeEdit):    def __init__(self, parent=None):        super().__init__(parent)        self.lineEdit().clear()  # 初始化时让输入框为空
def validate(self, input: str, pos: int) -> Tuple[QValidator.State, str, int]: if not input: # 允许接受空串 return QValidator.Intermediate, '', 0 return super().validate(input, pos)
def textFromDateTime(self, dateTime: QDateTime) -> str: return super().textFromDateTime(dateTime) if self.text() else ''
复制代码


就这么简单!随后你会惊奇的发现,如果初始化后不设置时间 ( `setDate` 、`setDateTime` ... 等方法 ) 的话,点击 **步进按钮** 或 **弹出日历按钮** 时,居然没有文本显示了?莫慌,只要再重写 `mousePressEvent` 方法:


def mousePressEvent(self, evt: QMouseEvent) -> None:    super().mousePressEvent(evt)    if not self.text():        self.setDateTime(QDateTime.currentDateTime())
复制代码


即可!如果设置了 setCalendarPopup(True) ,并且要求在弹出日历时先不设置文本,而是等选择了日历的时间后再设置,则需要额外定制。具体我说一下思路,可以根据需求微调。


因为设置 calendarWidget 的时间时 QDateTimeEdit 的文本也会跟着改变,反之也是如此 ( calendarWidget 时间也会随着 QDateTimeEdit 变化 ) 。可以在 mousePressEvent 方法中阻止 calendarWidget 发射信号,为其设置上指定的日期后,再解除阻止。然后在连接了 calendarWidget 的信号方法 ( selectionChangedclicked ... 等) 中自行设置 QDateTimeEdit 的显示内容。为保证信号只连接一次 ,可以重写 setCalendarPopup 方法:


def mousePressEvent(self, evt: QMouseEvent) -> None:    super().mousePressEvent(evt)    if not self.text():        # 阻止 calendarWidget 自行改变 QDateTimeEdit 的显示时间        (w := self.calendarWidget()).blockSignals(True)        w.setSelectedDate(QDate.currentDate())        w.blockSignals(False)
def setCalendarPopup(self, enable: bool) -> None: super().setCalendarPopup(enable) if enable: # 保证信号只连接一次 if not (w := self.calendarWidget()).receivers(w.clicked): w.clicked.connect(self.setDate)
复制代码


另附上便捷设置 QDateTimeEdit 时间的方法:


def setDateTime(self, dateTime: Union[QDateTime, str]):    self._set_time(dateTime, QDateTime)
def setDate(self, date: Union[QDate, str]): self._set_time(date, QDate)
def setTime(self, time: Union[QTime, str]): self._set_time(time, QTime)
def _set_time(self, t: Union[QDate, QTime, QDateTime], cls): fmt = self.displayFormat() t = cls.fromString(t, fmt) if isinstance(t, str) else t # 这里不用担心给定的字符串会显示出错, # 因为中间还会经过 validate、textFromDateTime 方法, # 验证后返回最终被显示的文本,验证无效则不会显示在输入框中。 self.lineEdit().setText(t.toString(fmt))
复制代码


用户头像

一代咩神

关注

还未添加个人签名 2019.04.18 加入

还未添加个人简介

评论

发布
暂无评论
PyQt5 实现可空值的 QDateTimeEdit