# Authors: Joe VanAndel and Greg McFarlane
class TimeCounter(Pmw
.MegaWidget
):
A TimeCounter is a single-line entry widget with Up and Down arrows
which increment and decrement the Time value in the entry.
def __init__(self
, parent
= None, **kw
):
# Define the megawidget options.
('buttonaspect', 1.0, INITOPT
),
('labelmargin', 0, INITOPT
),
('labelpos', None, INITOPT
),
('max', None, self
._max
),
('min', None, self
._min
),
('repeatrate', 50, None),
('value', None, INITOPT
),
self
.defineoptions(kw
, optiondefs
)
# Initialise the base class (after defining the options).
Pmw
.MegaWidget
.__init
__(self
, parent
)
self
._createComponents
(kw
)
value
= time
.strftime('%H:%M:%S', time
.localtime(now
))
# Check keywords and initialise options.
def _createComponents(self
, kw
):
interior
= self
.interior()
# If there is no label, put the arrows and the entry directly
# into the interior, otherwise create a frame for them. In
# either case the border around the arrows and the entry will
# be raised (but not around the label).
if self
['labelpos'] is None:
if not kw
.has_key('hull_relief'):
frame
.configure(relief
= 'raised')
if not kw
.has_key('hull_borderwidth'):
frame
.configure(borderwidth
= 1)
frame
= self
.createcomponent('frame',
Tkinter
.Frame
, (interior
,),
relief
= 'raised', borderwidth
= 1)
frame
.grid(column
=2, row
=2, sticky
='nsew')
interior
.grid_columnconfigure(2, weight
=1)
interior
.grid_rowconfigure(2, weight
=1)
# Create the down arrow buttons.
# Create the hour down arrow.
self
._downHourArrowBtn
= self
.createcomponent('downhourarrow',
Tkinter
.Canvas
, (frame
,),
width
= 16, height
= 16, relief
= 'raised', borderwidth
= 2)
self
.arrowDirection
[self
._downHourArrowBtn
] = 'down'
self
._downHourArrowBtn
.grid(column
= 0, row
= 2)
# Create the minute down arrow.
self
._downMinuteArrowBtn
= self
.createcomponent('downminutearrow',
Tkinter
.Canvas
, (frame
,),
width
= 16, height
= 16, relief
= 'raised', borderwidth
= 2)
self
.arrowDirection
[self
._downMinuteArrowBtn
] = 'down'
self
._downMinuteArrowBtn
.grid(column
= 1, row
= 2)
# Create the second down arrow.
self
._downSecondArrowBtn
= self
.createcomponent('downsecondarrow',
Tkinter
.Canvas
, (frame
,),
width
= 16, height
= 16, relief
= 'raised', borderwidth
= 2)
self
.arrowDirection
[self
._downSecondArrowBtn
] = 'down'
self
._downSecondArrowBtn
.grid(column
= 2, row
= 2)
# Create the entry fields.
# Create the hour entry field.
self
._hourCounterEntry
= self
.createcomponent('hourentryfield',
(('hourentry', 'hourentryfield_entry'),), None,
Pmw
.EntryField
, (frame
,), validate
='integer', entry_width
= 2)
self
._hourCounterEntry
.grid(column
= 0, row
= 1, sticky
= 'news')
# Create the minute entry field.
self
._minuteCounterEntry
= self
.createcomponent('minuteentryfield',
(('minuteentry', 'minuteentryfield_entry'),), None,
Pmw
.EntryField
, (frame
,), validate
='integer', entry_width
= 2)
self
._minuteCounterEntry
.grid(column
= 1, row
= 1, sticky
= 'news')
# Create the second entry field.
self
._secondCounterEntry
= self
.createcomponent('secondentryfield',
(('secondentry', 'secondentryfield_entry'),), None,
Pmw
.EntryField
, (frame
,), validate
='integer', entry_width
= 2)
self
._secondCounterEntry
.grid(column
= 2, row
= 1, sticky
= 'news')
# Create the up arrow buttons.
# Create the hour up arrow.
self
._upHourArrowBtn
= self
.createcomponent('uphourarrow',
Tkinter
.Canvas
, (frame
,),
width
= 16, height
= 16, relief
= 'raised', borderwidth
= 2)
self
.arrowDirection
[self
._upHourArrowBtn
] = 'up'
self
._upHourArrowBtn
.grid(column
= 0, row
= 0)
# Create the minute up arrow.
self
._upMinuteArrowBtn
= self
.createcomponent('upminutearrow',
Tkinter
.Canvas
, (frame
,),
width
= 16, height
= 16, relief
= 'raised', borderwidth
= 2)
self
.arrowDirection
[self
._upMinuteArrowBtn
] = 'up'
self
._upMinuteArrowBtn
.grid(column
= 1, row
= 0)
# Create the second up arrow.
self
._upSecondArrowBtn
= self
.createcomponent('upsecondarrow',
Tkinter
.Canvas
, (frame
,),
width
= 16, height
= 16, relief
= 'raised', borderwidth
= 2)
self
.arrowDirection
[self
._upSecondArrowBtn
] = 'up'
self
._upSecondArrowBtn
.grid(column
= 2, row
= 0)
frame
.grid_columnconfigure(col
, weight
= 1, pad
= padx
)
frame
.grid_rowconfigure(0, pad
= pady
)
frame
.grid_rowconfigure(2, pad
= pady
)
frame
.grid_rowconfigure(1, weight
= 1)
self
.createlabel(interior
)
self
._upHourArrowBtn
.bind('<Configure>',
lambda event
, s
=self
,button
=self
._upHourArrowBtn
:
s
._drawArrow
(button
, 'up'))
self
._upHourArrowBtn
.bind('<1>',
lambda event
, s
=self
,button
=self
._upHourArrowBtn
:
s
._countUp
(button
, 3600))
self
._upHourArrowBtn
.bind('<Any-ButtonRelease-1>',
lambda event
, s
=self
, button
=self
._upHourArrowBtn
:
self
._upMinuteArrowBtn
.bind('<Configure>',
lambda event
, s
=self
,button
=self
._upMinuteArrowBtn
:
s
._drawArrow
(button
, 'up'))
self
._upMinuteArrowBtn
.bind('<1>',
lambda event
, s
=self
,button
=self
._upMinuteArrowBtn
:
self
._upMinuteArrowBtn
.bind('<Any-ButtonRelease-1>',
lambda event
, s
=self
, button
=self
._upMinuteArrowBtn
:
self
._upSecondArrowBtn
.bind('<Configure>',
lambda event
, s
=self
,button
=self
._upSecondArrowBtn
:
s
._drawArrow
(button
, 'up'))
self
._upSecondArrowBtn
.bind('<1>',
lambda event
, s
=self
,button
=self
._upSecondArrowBtn
:
self
._upSecondArrowBtn
.bind('<Any-ButtonRelease-1>',
lambda event
, s
=self
, button
=self
._upSecondArrowBtn
:
self
._downHourArrowBtn
.bind('<Configure>',
lambda event
, s
=self
,button
=self
._downHourArrowBtn
:
s
._drawArrow
(button
, 'down'))
self
._downHourArrowBtn
.bind('<1>',
lambda event
, s
=self
,button
=self
._downHourArrowBtn
:
s
._countDown
(button
, 3600))
self
._downHourArrowBtn
.bind('<Any-ButtonRelease-1>',
lambda event
, s
=self
, button
=self
._downHourArrowBtn
:
self
._downMinuteArrowBtn
.bind('<Configure>',
lambda event
, s
=self
,button
=self
._downMinuteArrowBtn
:
s
._drawArrow
(button
, 'down'))
self
._downMinuteArrowBtn
.bind('<1>',
lambda event
, s
=self
,button
=self
._downMinuteArrowBtn
:
s
._countDown
(button
, 60))
self
._downMinuteArrowBtn
.bind('<Any-ButtonRelease-1>',
lambda event
, s
=self
, button
=self
._downMinuteArrowBtn
:
self
._downSecondArrowBtn
.bind('<Configure>',
lambda event
, s
=self
,button
=self
._downSecondArrowBtn
:
s
._drawArrow
(button
, 'down'))
self
._downSecondArrowBtn
.bind('<1>',
lambda event
, s
=self
, button
=self
._downSecondArrowBtn
:
self
._downSecondArrowBtn
.bind('<Any-ButtonRelease-1>',
lambda event
, s
=self
, button
=self
._downSecondArrowBtn
:
self
._hourCounterEntry
.component('entry').bind(
'<Return>', self
._invoke
)
self
._minuteCounterEntry
.component('entry').bind(
'<Return>', self
._invoke
)
self
._secondCounterEntry
.component('entry').bind(
'<Return>', self
._invoke
)
self
._hourCounterEntry
.bind('<Configure>', self
._resizeArrow
)
self
._minuteCounterEntry
.bind('<Configure>', self
._resizeArrow
)
self
._secondCounterEntry
.bind('<Configure>', self
._resizeArrow
)
def _drawArrow(self
, arrow
, direction
):
Pmw
.drawarrow(arrow
, self
['hourentry_foreground'], direction
, 'arrow')
def _resizeArrow(self
, event
= None):
for btn
in (self
._upHourArrowBtn
, self
._upMinuteArrowBtn
,
self
._downMinuteArrowBtn
, self
._downSecondArrowBtn
):
bw
= (string
.atoi(btn
['borderwidth']) +
string
.atoi(btn
['highlightthickness']))
newHeight
= self
._hourCounterEntry
.winfo_reqheight() - 2 * bw
newWidth
= int(newHeight
* self
['buttonaspect'])
btn
.configure(width
=newWidth
, height
=newHeight
)
self
._drawArrow
(btn
, self
.arrowDirection
[btn
])
self
._minVal
= Pmw
.timestringtoseconds(min)
self
._maxVal
= Pmw
.timestringtoseconds(max)
def setvalue(self
, text
):
list = string
.split(text
, ':')
raise ValueError, 'invalid value: ' + text
self
._hour
= string
.atoi(list[0])
self
._minute
= string
.atoi(list[1])
self
._second
= string
.atoi(list[2])
return '%02d:%02d:%02d' % (self
._hour
, self
._minute
, self
._second
)
return self
._hour
* 3600 + self
._minute
* 60 + self
._second
def _countUp(self
, button
, increment
):
self
._relief
= self
._upHourArrowBtn
.cget('relief')
button
.configure(relief
='sunken')
self
._count
(1, 'start', increment
)
def _countDown(self
, button
, increment
):
self
._relief
= self
._downHourArrowBtn
.cget('relief')
button
.configure(relief
='sunken')
self
._count
(-1, 'start', increment
)
def increment(self
, seconds
= 1):
self
._count
(1, 'force', seconds
)
def decrement(self
, seconds
= 1):
self
._count
(-1, 'force', seconds
)
def _count(self
, factor
, newFlag
= None, increment
= 1):
if self
._flag
== 'stopped':
value
= (string
.atoi(self
._hourCounterEntry
.get()) *3600) + \
(string
.atoi(self
._minuteCounterEntry
.get()) *60) + \
string
.atoi(self
._secondCounterEntry
.get()) + \
if max is not None and value
> max:
self
._minute
= (value
- (self
._hour
*3600)) / 60
self
._second
= value
- (self
._hour
*3600) - (self
._minute
*60)
if self
._flag
== 'start':
delay
= self
['repeatrate']
self
._timerId
= self
.after(
delay
, lambda self
=self
, factor
=factor
,increment
=increment
:
self
._count
(factor
,'running', increment
))
self
._hourCounterEntry
.setentry('%02d' % self
._hour
)
self
._minuteCounterEntry
.setentry('%02d' % self
._minute
)
self
._secondCounterEntry
.setentry('%02d' % self
._second
)
def _stopUpDown(self
, button
):
if self
._timerId
is not None:
self
.after_cancel(self
._timerId
)
button
.configure(relief
=self
._relief
)
def _invoke(self
, event
):
if self
._timerId
is not None:
self
.after_cancel(self
._timerId
)
Pmw
.MegaWidget
.destroy(self
)