# Authors: Joe VanAndel, Greg McFarlane and Daniel Michelson
class FullTimeCounter(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.
('autorepeat', 1, INITOPT
),
('buttonaspect', 1.0, INITOPT
),
('initwait', 300, INITOPT
),
('labelmargin', 0, INITOPT
),
('labelpos', None, INITOPT
),
('repeatrate', 50, INITOPT
),
self
.defineoptions(kw
, optiondefs
)
# Initialise the base class (after defining the options).
Pmw
.MegaWidget
.__init
__(self
, parent
)
if value
is None or value
== '':
value
= time
.strftime('%Y:%m:%d:%H:%M',time
.gmtime(now
))
self
._setTimeFromStr
(value
)
# Check keywords and initialise options.
def _createComponents(self
):
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:
frame
= self
.createcomponent('frame',
Tkinter
.Frame
, (interior
,))
frame
.grid(column
=2, row
=2, sticky
='nsew')
interior
.grid_columnconfigure(2, weight
=1)
interior
.grid_rowconfigure(2, weight
=1)
frame
.configure(relief
= 'raised', borderwidth
= 1)
# Create the down arrow buttons.
# Create the year down arrow.
self
._downYearArrowBtn
= self
.createcomponent('downyeararrow',
Tkinter
.Canvas
, (frame
,),
width
= 16, height
= 16, relief
= 'raised', borderwidth
= 2)
self
.arrowDirection
[self
._downYearArrowBtn
] = 0
self
._downYearArrowBtn
.grid(column
= 0, row
= 2)
# Create the month down arrow.
self
._downMonthArrowBtn
= self
.createcomponent('downmontharrow',
Tkinter
.Canvas
, (frame
,),
width
= 16, height
= 16, relief
= 'raised', borderwidth
= 2)
self
.arrowDirection
[self
._downMonthArrowBtn
] = 0
self
._downMonthArrowBtn
.grid(column
= 1, row
= 2)
# Create the day down arrow.
self
._downDayArrowBtn
= self
.createcomponent('downdayarrow',
Tkinter
.Canvas
, (frame
,),
width
= 16, height
= 16, relief
= 'raised', borderwidth
= 2)
self
.arrowDirection
[self
._downDayArrowBtn
] = 0
self
._downDayArrowBtn
.grid(column
= 2, row
= 2)
# 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
] = 0
self
._downHourArrowBtn
.grid(column
= 3, 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
] = 0
self
._downMinuteArrowBtn
.grid(column
= 4, row
= 2)
# Create the entry fields.
# Create the year entry field.
self
._yearCounterEntry
= self
.createcomponent('yearentryfield',
(('yearentry', 'yearentryfield_entry'),), None,
Pmw
.EntryField
, (frame
,), validate
='integer', entry_width
= 4)
self
._yearCounterEntry
.grid(column
= 0, row
= 1, sticky
= 'news')
# Create the month entry field.
self
._monthCounterEntry
= self
.createcomponent('monthentryfield',
(('monthentry', 'monthentryfield_entry'),), None,
Pmw
.EntryField
, (frame
,), validate
='integer', entry_width
= 2)
self
._monthCounterEntry
.grid(column
= 1, row
= 1, sticky
= 'news')
# Create the day entry field.
self
._dayCounterEntry
= self
.createcomponent('dayentryfield',
(('dayentry', 'dayentryfield_entry'),), None,
Pmw
.EntryField
, (frame
,), validate
='integer', entry_width
= 2)
self
._dayCounterEntry
.grid(column
= 2, row
= 1, sticky
= 'news')
# 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
= 3, 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
= 4, row
= 1, sticky
= 'news')
# Create the up arrow buttons.
# Create the year up arrow.
self
._upYearArrowBtn
= self
.createcomponent('upyeararrow',
Tkinter
.Canvas
, (frame
,),
width
= 16, height
= 16, relief
= 'raised', borderwidth
= 2)
self
.arrowDirection
[self
._upYearArrowBtn
] = 1
self
._upYearArrowBtn
.grid(column
= 0, row
= 0)
# Create the month up arrow.
self
._upMonthArrowBtn
= self
.createcomponent('upmontharrow',
Tkinter
.Canvas
, (frame
,),
width
= 16, height
= 16, relief
= 'raised', borderwidth
= 2)
self
.arrowDirection
[self
._upMonthArrowBtn
] = 1
self
._upMonthArrowBtn
.grid(column
= 1, row
= 0)
# Create the day up arrow.
self
._upDayArrowBtn
= self
.createcomponent('updayarrow',
Tkinter
.Canvas
, (frame
,),
width
= 16, height
= 16, relief
= 'raised', borderwidth
= 2)
self
.arrowDirection
[self
._upDayArrowBtn
] = 1
self
._upDayArrowBtn
.grid(column
= 2, row
= 0)
# 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
] = 1
self
._upHourArrowBtn
.grid(column
= 3, 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
] = 1
self
._upMinuteArrowBtn
.grid(column
= 4, row
= 0)
for col
in range(5): # YY, MM, DD, HH, mm
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
._upYearArrowBtn
.bind('<Configure>',
lambda event
, s
=self
,button
=self
._upYearArrowBtn
:
self
._upYearArrowBtn
.bind('<1>',
lambda event
, s
=self
,button
=self
._upYearArrowBtn
:
self
._upYearArrowBtn
.bind('<Any-ButtonRelease-1>',
lambda event
, s
=self
, button
=self
._upYearArrowBtn
:
self
._upMonthArrowBtn
.bind('<Configure>',
lambda event
, s
=self
,button
=self
._upMonthArrowBtn
:
self
._upMonthArrowBtn
.bind('<1>',
lambda event
, s
=self
,button
=self
._upMonthArrowBtn
:
self
._upMonthArrowBtn
.bind('<Any-ButtonRelease-1>',
lambda event
, s
=self
, button
=self
._upMonthArrowBtn
:
self
._upDayArrowBtn
.bind('<Configure>',
lambda event
, s
=self
,button
=self
._upDayArrowBtn
:
self
._upDayArrowBtn
.bind('<1>',
lambda event
, s
=self
,button
=self
._upDayArrowBtn
:
self
._upDayArrowBtn
.bind('<Any-ButtonRelease-1>',
lambda event
, s
=self
, button
=self
._upDayArrowBtn
:
self
._upHourArrowBtn
.bind('<Configure>',
lambda event
, s
=self
,button
=self
._upHourArrowBtn
:
self
._upHourArrowBtn
.bind('<1>',
lambda event
, s
=self
,button
=self
._upHourArrowBtn
:
self
._upHourArrowBtn
.bind('<Any-ButtonRelease-1>',
lambda event
, s
=self
, button
=self
._upHourArrowBtn
:
self
._upMinuteArrowBtn
.bind('<Configure>',
lambda event
, s
=self
,button
=self
._upMinuteArrowBtn
:
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
._downYearArrowBtn
.bind('<Configure>',
lambda event
, s
=self
,button
=self
._downYearArrowBtn
:
self
._downYearArrowBtn
.bind('<1>',
lambda event
, s
=self
,button
=self
._downYearArrowBtn
:
self
._downYearArrowBtn
.bind('<Any-ButtonRelease-1>',
lambda event
, s
=self
, button
=self
._downYearArrowBtn
:
self
._downMonthArrowBtn
.bind('<Configure>',
lambda event
, s
=self
,button
=self
._downMonthArrowBtn
:
self
._downMonthArrowBtn
.bind('<1>',
lambda event
, s
=self
,button
=self
._downMonthArrowBtn
:
self
._downMonthArrowBtn
.bind('<Any-ButtonRelease-1>',
lambda event
, s
=self
, button
=self
._downMonthArrowBtn
:
self
._downDayArrowBtn
.bind('<Configure>',
lambda event
, s
=self
,button
=self
._downDayArrowBtn
:
self
._downDayArrowBtn
.bind('<1>',
lambda event
, s
=self
,button
=self
._downDayArrowBtn
:
self
._downDayArrowBtn
.bind('<Any-ButtonRelease-1>',
lambda event
, s
=self
, button
=self
._downDayArrowBtn
:
self
._downHourArrowBtn
.bind('<Configure>',
lambda event
, s
=self
,button
=self
._downHourArrowBtn
:
self
._downHourArrowBtn
.bind('<1>',
lambda event
, s
=self
,button
=self
._downHourArrowBtn
:
self
._downHourArrowBtn
.bind('<Any-ButtonRelease-1>',
lambda event
, s
=self
, button
=self
._downHourArrowBtn
:
self
._downMinuteArrowBtn
.bind('<Configure>',
lambda event
, s
=self
,button
=self
._downMinuteArrowBtn
:
self
._downMinuteArrowBtn
.bind('<1>',
lambda event
, s
=self
,button
=self
._downMinuteArrowBtn
: s
._countDown
(button
))
self
._downMinuteArrowBtn
.bind('<Any-ButtonRelease-1>',
lambda event
, s
=self
, button
=self
._downMinuteArrowBtn
:
self
._yearCounterEntry
.bind('<Return>', self
.invoke
)
self
._monthCounterEntry
.bind('<Return>', self
.invoke
)
self
._dayCounterEntry
.bind('<Return>', self
.invoke
)
self
._hourCounterEntry
.bind('<Return>', self
.invoke
)
self
._minuteCounterEntry
.bind('<Return>', self
.invoke
)
self
._yearCounterEntry
.bind('<Configure>', self
._resizeArrow
)
self
._monthCounterEntry
.bind('<Configure>', self
._resizeArrow
)
self
._dayCounterEntry
.bind('<Configure>', self
._resizeArrow
)
self
._hourCounterEntry
.bind('<Configure>', self
._resizeArrow
)
self
._minuteCounterEntry
.bind('<Configure>', self
._resizeArrow
)
def _drawArrow(self
, arrow
, direction
):
fg
= self
._yearCounterEntry
.cget('entry_foreground')
bw
= (string
.atoi(arrow
['borderwidth']) +
string
.atoi(arrow
['highlightthickness'])) / 2
h
= string
.atoi(arrow
['height']) + 2 * bw
w
= string
.atoi(arrow
['width']) + 2 * bw
0.25 * w
+ bw
, 0.25 * h
+ bw
,
0.50 * w
+ bw
, 0.75 * h
+ bw
,
0.75 * w
+ bw
, 0.25 * h
+ bw
,
0.25 * w
+ bw
, 0.75 * h
+ bw
,
0.50 * w
+ bw
, 0.25 * h
+ bw
,
0.75 * w
+ bw
, 0.75 * h
+ bw
,
def _resizeArrow(self
, event
= None):
for btn
in (self
._upYearArrowBtn
, self
._upMonthArrowBtn
,
self
._upDayArrowBtn
, self
._upHourArrowBtn
,
self
._upMinuteArrowBtn
, self
._downYearArrowBtn
,
self
._downMonthArrowBtn
, self
._downDayArrowBtn
,
self
._downHourArrowBtn
, self
._downMinuteArrowBtn
):
bw
= (string
.atoi(btn
['borderwidth']) + \
string
.atoi(btn
['highlightthickness']))
newHeight
= self
._yearCounterEntry
.winfo_reqheight() - 2 * bw
newWidth
= newHeight
* self
['buttonaspect']
btn
.configure(width
=newWidth
, height
=newHeight
)
self
._drawArrow
(btn
, self
.arrowDirection
[btn
])
def _setTimeFromStr(self
, str):
list = string
.split(str, ':')
raise ValueError, 'invalid value: ' + str
self
._year
= string
.atoi(list[0])
self
._month
= string
.atoi(list[1])
self
._day
= string
.atoi(list[2])
self
._hour
= string
.atoi(list[3])
self
._minute
= string
.atoi(list[4])
return '%04d:%02d:%02d:%02d:%02d' % (self
._year
, self
._month
,
def _countUp(self
, button
):
self
._relief
= self
._upYearArrowBtn
.cget('relief')
button
.configure(relief
='sunken')
if button
== self
._upYearArrowBtn
: datetype
= "year"
elif button
== self
._upMonthArrowBtn
: datetype
= "month"
elif button
== self
._upDayArrowBtn
: datetype
= "day"
elif button
== self
._upHourArrowBtn
: datetype
= "hour"
elif button
== self
._upMinuteArrowBtn
: datetype
= "minute"
self
._count
(1, datetype
, 'start')
def _countDown(self
, button
):
self
._relief
= self
._downYearArrowBtn
.cget('relief')
button
.configure(relief
='sunken')
if button
== self
._downYearArrowBtn
: datetype
= "year"
elif button
== self
._downMonthArrowBtn
: datetype
= "month"
elif button
== self
._downDayArrowBtn
: datetype
= "day"
elif button
== self
._downHourArrowBtn
: datetype
= "hour"
elif button
== self
._downMinuteArrowBtn
: datetype
= "minute"
self
._count
(-1, datetype
, 'start')
def _count(self
, factor
, datetype
, newFlag
=None):
if self
._flag
== 'stopped':
if datetype
== "year": self
._year
= self
._year
+ factor
elif datetype
== "month": self
._month
= self
._month
+ factor
elif datetype
== "day": self
._day
= self
._day
+ factor
elif datetype
== "hour": self
._hour
= self
._hour
+ factor
elif datetype
== "minute": self
._minute
= self
._minute
+ factor
secs
= time
.mktime((self
._year
, self
._month
, self
._day
, self
._hour
,
self
._minute
, 0, 0, 0, -1))
tt
= time
.localtime(secs
) # NOT gmtime!
if self
._flag
== 'start':
delay
= self
['repeatrate']
self
._timerId
= self
.after(
delay
, lambda self
=self
, factor
=factor
, datetype
=datetype
:
self
._count
(factor
, datetype
, 'running'))
self
._yearCounterEntry
.setentry('%04d' % self
._year
)
self
._monthCounterEntry
.setentry('%02d' % self
._month
)
self
._dayCounterEntry
.setentry('%02d' % self
._day
)
self
._hourCounterEntry
.setentry('%02d' % self
._hour
)
self
._minuteCounterEntry
.setentry('%02d' % self
._minute
)
def _stopUpDown(self
, button
):
if self
._timerId
is not None:
self
.after_cancel(self
._timerId
)
button
.configure(relief
=self
._relief
)
def invoke(self
, event
= None):
if self
._timerId
is not None:
self
.after_cancel(self
._timerId
)
Pmw
.MegaWidget
.destroy(self
)
stringVal
= _time
.getstring()
root
.title('FullTimeCounter')
exitButton
= Tkinter
.Button(root
, text
= 'Exit', command
= root
.destroy
)
exitButton
.pack(side
= 'bottom')
_time
= FullTimeCounter(root
,
label_text
= 'YYYY:MM:DD:HH:mm')
_time
.pack(fill
= 'both', expand
= 1, padx
=10, pady
=5)
button
= Tkinter
.Button(root
, text
= 'Show', command
= showString
)