📄 numctrl.py
字号:
if self._allowNone:
## dbg('calling base BaseMaskedTextCtrl._SetValue(self, "%s")' % value)
BaseMaskedTextCtrl._SetValue(self, value)
self.Refresh()
return
elif self._min > 0 and self.IsLimited():
replacement = self._min
else:
replacement = 0
## dbg('empty value; setting replacement:', replacement)
if replacement is None:
# Go get the integer portion about to be set and verify its validity
intstart, intend = self._fields[0]._extent
## dbg('intstart, intend:', intstart, intend)
## dbg('raw integer:"%s"' % value[intstart:intend])
int = self._GetNumValue(value[intstart:intend])
numval = self._fromGUI(value)
## dbg('integer: "%s"' % int)
try:
fracval = self.GetFraction(value)
except ValueError, e:
## dbg('Exception:', e, 'must be out of bounds; disallow value')
self._disallowValue()
## dbg(indent=0)
return
if fracval == 0.0:
## dbg('self._isNeg?', self._isNeg)
if int == '-' and self._oldvalue < 0 and not self._typedSign:
## dbg('just a negative sign; old value < 0; setting replacement of 0')
replacement = 0
self._isNeg = False
elif int[:2] == '-0' and self._fractionWidth == 0:
if self._oldvalue < 0:
## dbg('-0; setting replacement of 0')
replacement = 0
self._isNeg = False
elif not self._limited or (self._min < -1 and self._max >= -1):
## dbg('-0; setting replacement of -1')
replacement = -1
self._isNeg = True
else:
# limited and -1 is out of bounds
self._disallowValue()
## dbg(indent=0)
return
elif int == '-' and (self._oldvalue >= 0 or self._typedSign) and self._fractionWidth == 0:
if not self._limited or (self._min < -1 and self._max >= -1):
## dbg('just a negative sign; setting replacement of -1')
replacement = -1
else:
# limited and -1 is out of bounds
self._disallowValue()
## dbg(indent=0)
return
elif( self._typedSign
and int.find('-') != -1
and self._limited
and not self._min <= numval <= self._max):
# changed sign resulting in value that's now out-of-bounds;
# disallow
self._disallowValue()
## dbg(indent=0)
return
if replacement is None:
if int and int != '-':
try:
string.atol(int)
except ValueError:
# integer requested is not legal. This can happen if the user
# is attempting to insert a digit in the middle of the control
# resulting in something like " 3 45". Disallow such actions:
## dbg('>>>>>>>>>>>>>>>> "%s" does not convert to a long!' % int)
if not wx.Validator_IsSilent():
wx.Bell()
sel_start, sel_to = self._GetSelection()
## dbg('queuing reselection of (%d, %d)' % (sel_start, sel_to))
wx.CallAfter(self.SetInsertionPoint, sel_start) # preserve current selection/position
wx.CallAfter(self.SetSelection, sel_start, sel_to)
## dbg(indent=0)
return
if int[0] == '0' and len(int) > 1:
## dbg('numvalue: "%s"' % numvalue.replace(' ', ''))
if self._fractionWidth:
value = self._toGUI(string.atof(numvalue))
else:
value = self._toGUI(string.atol(numvalue))
## dbg('modified value: "%s"' % value)
self._typedSign = False # reset state var
if replacement is not None:
# Value presented wasn't a legal number, but control should do something
# reasonable instead:
## dbg('setting replacement value:', replacement)
self._SetValue(self._toGUI(replacement))
sel_start = BaseMaskedTextCtrl.GetValue(self).find(str(abs(replacement))) # find where it put the 1, so we can select it
sel_to = sel_start + len(str(abs(replacement)))
## dbg('queuing selection of (%d, %d)' %(sel_start, sel_to))
wx.CallAfter(self.SetInsertionPoint, sel_start)
wx.CallAfter(self.SetSelection, sel_start, sel_to)
## dbg(indent=0)
return
# Otherwise, apply appropriate formatting to value:
# Because we're intercepting the value and adjusting it
# before a sign change is detected, we need to do this here:
if '-' in value or '(' in value:
self._isNeg = True
else:
self._isNeg = False
## dbg('value:"%s"' % value, 'self._useParens:', self._useParens)
if self._fractionWidth:
adjvalue = self._adjustFloat(self._GetNumValue(value).replace('.',self._decimalChar))
else:
adjvalue = self._adjustInt(self._GetNumValue(value))
## dbg('adjusted value: "%s"' % adjvalue)
sel_start, sel_to = self._GetSelection() # record current insertion point
## dbg('calling BaseMaskedTextCtrl._SetValue(self, "%s")' % adjvalue)
BaseMaskedTextCtrl._SetValue(self, adjvalue)
# After all actions so far scheduled, check that resulting cursor
# position is appropriate, and move if not:
wx.CallAfter(self._CheckInsertionPoint)
## dbg('finished NumCtrl::_SetValue', indent=0)
def _CheckInsertionPoint(self):
# If current insertion point is before the end of the integer and
# its before the 1st digit, place it just after the sign position:
## dbg('NumCtrl::CheckInsertionPoint', indent=1)
sel_start, sel_to = self._GetSelection()
text = self._GetValue()
if sel_to < self._fields[0]._extent[1] and text[sel_to] in (' ', '-', '('):
text, signpos, right_signpos = self._getSignedValue()
## dbg('setting selection(%d, %d)' % (signpos+1, signpos+1))
self.SetInsertionPoint(signpos+1)
self.SetSelection(signpos+1, signpos+1)
## dbg(indent=0)
def _OnErase( self, event=None, just_return_value=False ):
"""
This overrides the base control _OnErase, so that erasing around
grouping characters auto selects the digit before or after the
grouping character, so that the erasure does the right thing.
"""
## dbg('NumCtrl::_OnErase', indent=1)
if event is None: # called as action routine from Cut() operation.
key = wx.WXK_DELETE
else:
key = event.GetKeyCode()
#if grouping digits, make sure deletes next to group char always
# delete next digit to appropriate side:
if self._groupDigits:
value = BaseMaskedTextCtrl.GetValue(self)
sel_start, sel_to = self._GetSelection()
if key == wx.WXK_BACK:
# if 1st selected char is group char, select to previous digit
if sel_start > 0 and sel_start < len(self._mask) and value[sel_start:sel_to] == self._groupChar:
self.SetInsertionPoint(sel_start-1)
self.SetSelection(sel_start-1, sel_to)
# elif previous char is group char, select to previous digit
elif sel_start > 1 and sel_start == sel_to and value[sel_start-1:sel_start] == self._groupChar:
self.SetInsertionPoint(sel_start-2)
self.SetSelection(sel_start-2, sel_to)
elif key == wx.WXK_DELETE:
if( sel_to < len(self._mask) - 2 + (1 *self._useParens)
and sel_start == sel_to
and value[sel_to] == self._groupChar ):
self.SetInsertionPoint(sel_start)
self.SetSelection(sel_start, sel_to+2)
elif( sel_to < len(self._mask) - 2 + (1 *self._useParens)
and value[sel_start:sel_to] == self._groupChar ):
self.SetInsertionPoint(sel_start)
self.SetSelection(sel_start, sel_to+1)
## dbg(indent=0)
return BaseMaskedTextCtrl._OnErase(self, event, just_return_value)
def OnTextChange( self, event ):
"""
Handles an event indicating that the text control's value
has changed, and issue EVT_NUM event.
NOTE: using wxTextCtrl.SetValue() to change the control's
contents from within a EVT_CHAR handler can cause double
text events. So we check for actual changes to the text
before passing the events on.
"""
## dbg('NumCtrl::OnTextChange', indent=1)
if not BaseMaskedTextCtrl._OnTextChange(self, event):
## dbg(indent=0)
return
# else... legal value
value = self.GetValue()
if value != self._oldvalue:
try:
self.GetEventHandler().ProcessEvent(
NumberUpdatedEvent( self.GetId(), self.GetValue(), self ) )
except ValueError:
## dbg(indent=0)
return
# let normal processing of the text continue
event.Skip()
self._oldvalue = value # record for next event
## dbg(indent=0)
def _GetValue(self):
"""
Override of BaseMaskedTextCtrl to allow mixin to get the raw text value of the
control with this function.
"""
return wx.TextCtrl.GetValue(self)
def GetValue(self):
"""
Returns the current numeric value of the control.
"""
return self._fromGUI( BaseMaskedTextCtrl.GetValue(self) )
def SetValue(self, value):
"""
Sets the value of the control to the value specified.
The resulting actual value of the control may be altered to
conform with the bounds set on the control if limited,
or colored if not limited but the value is out-of-bounds.
A ValueError exception will be raised if an invalid value
is specified.
"""
## dbg('NumCtrl::SetValue(%s)' % value, indent=1)
BaseMaskedTextCtrl.SetValue( self, self._toGUI(value) )
## dbg(indent=0)
def SetIntegerWidth(self, value):
self.SetParameters(integerWidth=value)
def GetIntegerWidth(self):
return self._integerWidth
def SetFractionWidth(self, value):
self.SetParameters(fractionWidth=value)
def GetFractionWidth(self):
return self._fractionWidth
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 False and the minimum will not change from
its current setting. On success, the function returns True.
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.
If min > the max value allowed by the width of the control,
the function will return False, and the min will not be set.
"""
## dbg('NumCtrl::SetMin(%s)' % repr(min), indent=1)
if( self._max is None
or min is None
or (self._max is not None and self._max >= min) ):
try:
self.SetParameters(min=min)
bRet = True
except ValueError:
bRet = False
else:
bRet = False
## dbg(indent=0)
return bRet
def GetMin(self):
"""
Gets the lower bound value of the control. It will return
None if not specified.
"""
return self._min
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.
If max > the max value allowed by the width of the control,
the function will return False, and the max will not be set.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -