📄 timectrl.py
字号:
if value is None:
## dbg('getting control value')
value = self.GetValue()
## dbg('value = "%s"' % value)
if type(value) == types.UnicodeType:
value = str(value) # convert to regular string
valid = True # assume true
if type(value) == types.StringType:
# Construct constant wxDateTime, then try to parse the string:
wxdt = wx.DateTimeFromDMY(1, 0, 1970)
## dbg('attempting conversion')
value = value.strip() # (parser doesn't like leading spaces)
checkTime = wxdt.ParseTime(value)
valid = checkTime == len(value) # entire string parsed?
## dbg('checkTime == len(value)?', valid)
if not valid:
# deal with bug/deficiency in wx.DateTime:
try:
if wxdt.Format('%p') not in ('AM', 'PM') and checkTime in (5,8):
# couldn't parse the AM/PM field
raise ValueError('cannot convert string "%s" to valid time for the current locale; please use 24hr time instead' % value)
else:
## dbg(indent=0, suspend=0)
raise ValueError('cannot convert string "%s" to valid time' % value)
except:
raise ValueError('cannot convert string "%s" to valid time for the current locale; please use 24hr time instead' % value)
else:
if isinstance(value, wx.DateTime):
hour, minute, second = value.GetHour(), value.GetMinute(), value.GetSecond()
elif isinstance(value, wx.TimeSpan):
totalseconds = value.GetSeconds()
hour = totalseconds / 3600
minute = totalseconds / 60 - (hour * 60)
second = totalseconds - ((hour * 3600) + (minute * 60))
elif accept_mx and isinstance(value, DateTime.DateTimeType):
hour, minute, second = value.hour, value.minute, value.second
elif accept_mx and isinstance(value, DateTime.DateTimeDeltaType):
hour, minute, second = value.hour, value.minute, value.second
else:
# Not a valid function argument
if accept_mx:
error = 'GetWxDateTime requires wxDateTime, mxDateTime or parsable time string, passed %s'% repr(value)
else:
error = 'GetWxDateTime requires wxDateTime or parsable time string, passed %s'% repr(value)
## dbg(indent=0, suspend=0)
raise ValueError(error)
wxdt = wx.DateTimeFromDMY(1, 0, 1970)
wxdt.SetHour(hour)
wxdt.SetMinute(minute)
wxdt.SetSecond(second)
## dbg('wxdt:', wxdt, indent=0, suspend=0)
return wxdt
def SetMxDateTime(self, mxdt):
"""
Because SetValue can take an mx.DateTime, (if DateTime is importable),
this is now just an alias.
"""
self.SetValue(value)
def GetMxDateTime(self, value=None):
"""
Returns the value of the control as an mx.DateTime, with the date
portion set to January 1, 1970.
"""
if value is None:
t = self.GetValue(as_mxDateTime=True)
else:
# Convert string 1st to wxDateTime, then use components, since
# mx' DateTime.Parser.TimeFromString() doesn't handle AM/PM:
wxdt = self.GetWxDateTime(value)
hour, minute, second = wxdt.GetHour(), wxdt.GetMinute(), wxdt.GetSecond()
t = DateTime.DateTime(1970,1,1) + DateTimeDelta(0, hour, minute, second)
return t
def SetMin(self, min=None):
"""
Sets the minimum value of the control. If a value of None
is provided, then the control will have no explicit minimum value.
If the value specified is greater than the current maximum value,
then the function returns 0 and the minimum will not change from
its current setting. On success, the function returns 1.
If successful and the current value is lower than the new lower
bound, if the control is limited, the value will be automatically
adjusted to the new minimum value; if not limited, the value in the
control will be colored as invalid.
"""
## dbg('TimeCtrl::SetMin(%s)'% repr(min), indent=1)
if min is not None:
try:
min = self.GetWxDateTime(min)
self.__min = self._toGUI(min)
except:
## dbg('exception occurred', indent=0)
return False
else:
self.__min = min
if self.IsLimited() and not self.IsInBounds():
self.SetLimited(self.__limited) # force limited value:
else:
self._CheckValid()
ret = True
## dbg('ret:', ret, indent=0)
return ret
def GetMin(self, as_string = False):
"""
Gets the minimum value of the control.
If None, it will return None. Otherwise it will return
the current minimum bound on the control, as a wxDateTime
by default, or as a string if as_string argument is True.
"""
## dbg(suspend=1)
## dbg('TimeCtrl::GetMin, as_string?', as_string, indent=1)
if self.__min is None:
## dbg('(min == None)')
ret = self.__min
elif as_string:
ret = self.__min
## dbg('ret:', ret)
else:
try:
ret = self.GetWxDateTime(self.__min)
except:
## dbg(suspend=0)
## dbg('exception occurred', indent=0)
raise
## dbg('ret:', repr(ret))
## dbg(indent=0, suspend=0)
return ret
def SetMax(self, max=None):
"""
Sets the maximum value of the control. If a value of None
is provided, then the control will have no explicit maximum value.
If the value specified is less than the current minimum value, then
the function returns False and the maximum will not change from its
current setting. On success, the function returns True.
If successful and the current value is greater than the new upper
bound, if the control is limited the value will be automatically
adjusted to this maximum value; if not limited, the value in the
control will be colored as invalid.
"""
## dbg('TimeCtrl::SetMax(%s)' % repr(max), indent=1)
if max is not None:
try:
max = self.GetWxDateTime(max)
self.__max = self._toGUI(max)
except:
## dbg('exception occurred', indent=0)
return False
else:
self.__max = max
## dbg('max:', repr(self.__max))
if self.IsLimited() and not self.IsInBounds():
self.SetLimited(self.__limited) # force limited value:
else:
self._CheckValid()
ret = True
## dbg('ret:', ret, indent=0)
return ret
def GetMax(self, as_string = False):
"""
Gets the minimum value of the control.
If None, it will return None. Otherwise it will return
the current minimum bound on the control, as a wxDateTime
by default, or as a string if as_string argument is True.
"""
## dbg(suspend=1)
## dbg('TimeCtrl::GetMin, as_string?', as_string, indent=1)
if self.__max is None:
## dbg('(max == None)')
ret = self.__max
elif as_string:
ret = self.__max
## dbg('ret:', ret)
else:
try:
ret = self.GetWxDateTime(self.__max)
except:
## dbg(suspend=0)
## dbg('exception occurred', indent=0)
raise
## dbg('ret:', repr(ret))
## dbg(indent=0, suspend=0)
return ret
def SetBounds(self, min=None, max=None):
"""
This function is a convenience function for setting the min and max
values at the same time. The function only applies the maximum bound
if setting the minimum bound is successful, and returns True
only if both operations succeed.
**NOTE:** leaving out an argument will remove the corresponding bound.
"""
ret = self.SetMin(min)
return ret and self.SetMax(max)
def GetBounds(self, as_string = False):
"""
This function returns a two-tuple (min,max), indicating the
current bounds of the control. Each value can be None if
that bound is not set.
"""
return (self.GetMin(as_string), self.GetMax(as_string))
def SetLimited(self, limited):
"""
If called with a value of True, this function will cause the control
to limit the value to fall within the bounds currently specified.
If the control's value currently exceeds the bounds, it will then
be limited accordingly.
If called with a value of 0, this function will disable value
limiting, but coloring of out-of-bounds values will still take
place if bounds have been set for the control.
"""
## dbg('TimeCtrl::SetLimited(%d)' % limited, indent=1)
self.__limited = limited
if not limited:
self.SetMaskParameters(validRequired = False)
self._CheckValid()
## dbg(indent=0)
return
## dbg('requiring valid value')
self.SetMaskParameters(validRequired = True)
min = self.GetMin()
max = self.GetMax()
if min is None or max is None:
## dbg('both bounds not set; no further action taken')
return # can't limit without 2 bounds
elif not self.IsInBounds():
# set value to the nearest bound:
try:
value = self.GetWxDateTime()
except:
## dbg('exception occurred', indent=0)
raise
if min <= max: # valid range doesn't span midnight
## dbg('min <= max')
# which makes the "nearest bound" computation trickier...
# determine how long the "invalid" pie wedge is, and cut
# this interval in half for comparison purposes:
# Note: relies on min and max and value date portions
# always being the same.
interval = (min + wx.TimeSpan(24, 0, 0, 0)) - max
half_interval = wx.TimeSpan(
0, # hours
0, # minutes
interval.GetSeconds() / 2, # seconds
0) # msec
if value < min: # min is on next day, so use value on
# "next day" for "nearest" interval calculation:
cmp_value = value + wx.TimeSpan(24, 0, 0, 0)
else: # "before midnight; ok
cmp_value = value
if (cmp_value - max) > half_interval:
## dbg('forcing value to min (%s)' % min.FormatTime())
self.SetValue(min)
else:
## dbg('forcing value to max (%s)' % max.FormatTime())
self.SetValue(max)
else:
## dbg('max < min')
# therefore max < value < min guaranteed to be true,
# so "nearest bound" calculation is much easier:
if (value - max) >= (min - value):
# current value closer to min; pick that edge of pie wedge
## dbg('forcing value to min (%s)' % min.FormatTime())
self.SetValue(min)
else:
## dbg('forcing value to max (%s)' % max.FormatTime())
self.SetValue(max)
## dbg(indent=0)
def IsLimited(self):
"""
Returns True if the control is currently limiting the
value to fall within any current bounds. *Note:* can
be set even if there are no current bounds.
"""
return self.__limited
def IsInBounds(self, value=None):
"""
Returns True if no value is specified and the current value
of the control falls within the current bounds. As the clock
is a "circle", both minimum and maximum bounds must be set for
a value to ever be considered "out of bounds". This function can
also be called with a value to see if that value would fall within
the current bounds of the given control.
"""
if value is not None:
try:
value = self.GetWxDateTime(value) # try to regularize passed value
except ValueError:
## dbg('ValueError getting wxDateTime for %s' % repr(value), indent=0)
raise
## dbg('TimeCtrl::IsInBounds(%s)' % repr(value), indent=1)
if self.__min is None or self.__max is None:
## dbg(indent=0)
return True
elif value is None:
try:
value = self.GetWxDateTime()
except:
## dbg('exception occurred', indent=0)
raise
## dbg('value:', value.FormatTime())
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -