PyQt5 - QDateTimeEdit 旋转框翻转
PyQt5 - QDateTimeEdit spinbox rollover
我正在开发一个应用程序以从特定 FTP 平台下载日志文件,我还希望用户能够 select 开始和停止日期单独的 QDateTimeEdit 小部件。这将使程序选择合适的日志文件。
当用户连接到平台时,根据日志文件的可用性设置最小和最大 datetime
s,这工作正常,直到用户尝试使用旋转框更进一步例如,从 3 月 31 日到 4 月 1 日的按钮。小部件不会滚动到下个月。
我是否缺少启用或禁用翻转的属性?
我是否可以插入自定义 python (3.6) 代码来创建翻转?我的谷歌搜索除了 custom C++ code from 2008 和 stepBy
什么都没有得到,我读得不太好。
这是 .ui 文件的 XML 版本:
<widget class="QDateTimeEdit" name="timestart">
<property name="geometry">
<rect>
<x>510</x>
<y>155</y>
<width>126</width>
<height>22</height>
</rect>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="displayFormat">
<string notr="true">yyyy-MM-dd HH:mm:ss</string>
</property>
</widget>
<widget class="QDateTimeEdit" name="timeend">
<property name="geometry">
<rect>
<x>510</x>
<y>205</y>
<width>126</width>
<height>22</height>
</rect>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="displayFormat">
<string notr="true">yyyy-MM-dd HH:mm:ss</string>
</property>
</widget>
我意识到启用 calendarPopup
也是一种解决方法,但在设计方面,如果我能找到解决翻转问题的 pythonic 方法,我宁愿不这样做。
一个可能的解决方法是子class QDateTimeEdit 并覆盖两者stepEnabled
(which is responsible of showing enabled up/down arrows and allowing actual up/down step action) and then stepBy
以允许更改超出当前day/month/year.
限制的日期
不幸的是,这无法解决在 select 相应月份之前无法输入“无效”日期数字的问题(例如:您不能在 2 月输入 31),但可以实现由于旋转框、游标和完成器之间的相互作用,这样的结果确实复杂。
在下面的代码中,我实现了它,以便所有有效的 date/time 字段实际上都可以向上和向下:月、日、小时、分钟和秒。
class DateTimeFix(QtWidgets.QDateTimeEdit):
_overrideSteps = (
QtWidgets.QDateTimeEdit.MonthSection,
QtWidgets.QDateTimeEdit.DaySection,
QtWidgets.QDateTimeEdit.HourSection,
QtWidgets.QDateTimeEdit.MinuteSection,
QtWidgets.QDateTimeEdit.SecondSection,
)
def stepEnabled(self):
if self.currentSection() in self._overrideSteps:
return self.StepUpEnabled | self.StepDownEnabled
return super().stepEnabled()
def stepBy(self, steps):
section = self.currentSection()
if section not in self._overrideSteps:
super().stepBy(steps)
return
dt = self.dateTime()
section = self.currentSection()
if section == self.MonthSection:
dt = dt.addMonths(steps)
elif section == self.DaySection:
dt = dt.addDays(steps)
elif section == self.HourSection:
dt = dt.addSecs(3600 * steps)
elif section == self.MinuteSection:
dt = dt.addSecs(60 * steps)
else:
dt = dt.addSecs(steps)
self.setDateTime(dt)
由于您是在 Designer 中创建 UI,因此您需要在 Designer 中提升 QDateTimeEdit 才能使用上述 class。
简化的过程是:右键单击设计器中的 QDateTimeEdit 小部件,然后 select Promote to...
,从对话框类型“DateTimeFix”(class 名称)在“Promoted class name" 字段,然后键入要在其中放置上述 class 的文件的名称( 不带 .py
扩展名,就像您使用导入),确保基础 class 名称仍然正确(QDateTimeEdit),单击“添加”,然后单击“提升”。在此过程之后,您可以升级您可能在 ui 中拥有的所有其他 QDateTimeEdit(只需右键单击它们并从新的“升级到”子菜单中 select 它)。有关更详细的说明,请参阅 this answer。
我使用了上面@musicamante 所示的代码片段,并进行了一些调整,可能是因为我使用的是 PyQt6。 (基本上,将那些 .Section
和 .StepEnabledFlag
添加到枚举属性)
from PyQt6.QtWidgets import QDateTimeEdit
class DateTimeFix(QDateTimeEdit):
_overrideSteps = (
QDateTimeEdit.Section.MonthSection,
QDateTimeEdit.Section.DaySection,
QDateTimeEdit.Section.HourSection,
QDateTimeEdit.Section.MinuteSection,
QDateTimeEdit.Section.SecondSection,
)
def stepEnabled(self):
if self.currentSection() in self._overrideSteps:
return self.StepEnabledFlag.StepUpEnabled | self.StepEnabledFlag.StepDownEnabled
return super().stepEnabled()
def stepBy(self, steps):
section = self.currentSection()
if section not in self._overrideSteps:
super().stepBy(steps)
return
dt = self.dateTime()
section = self.currentSection()
if section == self.Section.MonthSection:
dt = dt.addMonths(steps)
elif section == self.Section.DaySection:
dt = dt.addDays(steps)
elif section == self.Section.HourSection:
dt = dt.addSecs(3600 * steps)
elif section == self.Section.MinuteSection:
dt = dt.addSecs(60 * steps)
else:
dt = dt.addSecs(steps)
self.setDateTime(dt)
我正在开发一个应用程序以从特定 FTP 平台下载日志文件,我还希望用户能够 select 开始和停止日期单独的 QDateTimeEdit 小部件。这将使程序选择合适的日志文件。
当用户连接到平台时,根据日志文件的可用性设置最小和最大 datetime
s,这工作正常,直到用户尝试使用旋转框更进一步例如,从 3 月 31 日到 4 月 1 日的按钮。小部件不会滚动到下个月。
我是否缺少启用或禁用翻转的属性?
我是否可以插入自定义 python (3.6) 代码来创建翻转?我的谷歌搜索除了 custom C++ code from 2008 和 stepBy
什么都没有得到,我读得不太好。
这是 .ui 文件的 XML 版本:
<widget class="QDateTimeEdit" name="timestart">
<property name="geometry">
<rect>
<x>510</x>
<y>155</y>
<width>126</width>
<height>22</height>
</rect>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="displayFormat">
<string notr="true">yyyy-MM-dd HH:mm:ss</string>
</property>
</widget>
<widget class="QDateTimeEdit" name="timeend">
<property name="geometry">
<rect>
<x>510</x>
<y>205</y>
<width>126</width>
<height>22</height>
</rect>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="displayFormat">
<string notr="true">yyyy-MM-dd HH:mm:ss</string>
</property>
</widget>
我意识到启用 calendarPopup
也是一种解决方法,但在设计方面,如果我能找到解决翻转问题的 pythonic 方法,我宁愿不这样做。
一个可能的解决方法是子class QDateTimeEdit 并覆盖两者stepEnabled
(which is responsible of showing enabled up/down arrows and allowing actual up/down step action) and then stepBy
以允许更改超出当前day/month/year.
不幸的是,这无法解决在 select 相应月份之前无法输入“无效”日期数字的问题(例如:您不能在 2 月输入 31),但可以实现由于旋转框、游标和完成器之间的相互作用,这样的结果确实复杂。
在下面的代码中,我实现了它,以便所有有效的 date/time 字段实际上都可以向上和向下:月、日、小时、分钟和秒。
class DateTimeFix(QtWidgets.QDateTimeEdit):
_overrideSteps = (
QtWidgets.QDateTimeEdit.MonthSection,
QtWidgets.QDateTimeEdit.DaySection,
QtWidgets.QDateTimeEdit.HourSection,
QtWidgets.QDateTimeEdit.MinuteSection,
QtWidgets.QDateTimeEdit.SecondSection,
)
def stepEnabled(self):
if self.currentSection() in self._overrideSteps:
return self.StepUpEnabled | self.StepDownEnabled
return super().stepEnabled()
def stepBy(self, steps):
section = self.currentSection()
if section not in self._overrideSteps:
super().stepBy(steps)
return
dt = self.dateTime()
section = self.currentSection()
if section == self.MonthSection:
dt = dt.addMonths(steps)
elif section == self.DaySection:
dt = dt.addDays(steps)
elif section == self.HourSection:
dt = dt.addSecs(3600 * steps)
elif section == self.MinuteSection:
dt = dt.addSecs(60 * steps)
else:
dt = dt.addSecs(steps)
self.setDateTime(dt)
由于您是在 Designer 中创建 UI,因此您需要在 Designer 中提升 QDateTimeEdit 才能使用上述 class。
简化的过程是:右键单击设计器中的 QDateTimeEdit 小部件,然后 select Promote to...
,从对话框类型“DateTimeFix”(class 名称)在“Promoted class name" 字段,然后键入要在其中放置上述 class 的文件的名称( 不带 .py
扩展名,就像您使用导入),确保基础 class 名称仍然正确(QDateTimeEdit),单击“添加”,然后单击“提升”。在此过程之后,您可以升级您可能在 ui 中拥有的所有其他 QDateTimeEdit(只需右键单击它们并从新的“升级到”子菜单中 select 它)。有关更详细的说明,请参阅 this answer。
我使用了上面@musicamante 所示的代码片段,并进行了一些调整,可能是因为我使用的是 PyQt6。 (基本上,将那些 .Section
和 .StepEnabledFlag
添加到枚举属性)
from PyQt6.QtWidgets import QDateTimeEdit
class DateTimeFix(QDateTimeEdit):
_overrideSteps = (
QDateTimeEdit.Section.MonthSection,
QDateTimeEdit.Section.DaySection,
QDateTimeEdit.Section.HourSection,
QDateTimeEdit.Section.MinuteSection,
QDateTimeEdit.Section.SecondSection,
)
def stepEnabled(self):
if self.currentSection() in self._overrideSteps:
return self.StepEnabledFlag.StepUpEnabled | self.StepEnabledFlag.StepDownEnabled
return super().stepEnabled()
def stepBy(self, steps):
section = self.currentSection()
if section not in self._overrideSteps:
super().stepBy(steps)
return
dt = self.dateTime()
section = self.currentSection()
if section == self.Section.MonthSection:
dt = dt.addMonths(steps)
elif section == self.Section.DaySection:
dt = dt.addDays(steps)
elif section == self.Section.HourSection:
dt = dt.addSecs(3600 * steps)
elif section == self.Section.MinuteSection:
dt = dt.addSecs(60 * steps)
else:
dt = dt.addSecs(steps)
self.setDateTime(dt)