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
的訊號方法 ( selectionChanged
、clicked
… 等) 中自行設定 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))
本作品採用《CC 協議》,轉載必須註明作者和本文連結