modulus
modulus

Reputation: 28

wxpython frame doesn't re-draw it's contents in while loop

I am creating a countdown to Christmas using wxpython as a GUI. I tried testing the script with the secondsLeft so that the seconds would be printed on the canvas. The program draws the seconds but they don't change as they're supposed to.

This is my code:

"""A simple contdown for Christmas using wxpython as a GUI"""
import wx
import datetime

#Setting our current time.
currentTime = datetime.datetime.now()
now = list(str(currentTime))
now = now[:19]
now = ''.join(now)

#Computing time left.
while now != '2015-12-25 1:00:00':

    if currentTime.month == 11:
        daysLeft = (30 - currentTime.day) + 24

    else:
        daysLeft = 25 - currentTime.day

    if currentTime.hour >= 12:
        hoursLeft = 25 - currentTime.hour

    else:
        hoursLeft = (12 - currentTime.hour) + 13

    minutesLeft = currentTime.minute
    secondsLeft = currentTime.second

    currentTime = datetime.datetime.now()
    now = list(str(currentTime))
    now = now[:19]
    now = ''.join(now)

    class AFrame(wx.Frame):
        def __init__ (self, parent=None, id=-1, title=None):
            wx.Frame.__init__(self, parent, id, title, size=(400, 400))
            self.statbmp = wx.StaticBitmap(self)
            self.draw_image()
            self.Refresh()

        def draw_image(self):
            # select the width and height of the blank bitmap
            # must fit frame
            w, h = 400, 400
            # create the blank bitmap as background
            draw_bmp = wx.EmptyBitmap(w, h)
            #create canvas.
            canvas = wx.MemoryDC(draw_bmp)
            #fill the canvas with white
            canvas.SetBrush(wx.Brush('white'))
            canvas.Clear()
            #get text dimentions.
            tw, th = canvas.GetTextExtent(str(secondsLeft))
            #draw the text.
            canvas.DrawText(str(secondsLeft), (w - tw) / 2, (h - th) / 2 )

            self.statbmp.SetBitmap(draw_bmp)

    app = wx.App(0)
    AFrame(title="Coundown to Christmas").Show()
    app.MainLoop() #Starts frame.

Upvotes: 0

Views: 291

Answers (2)

Rolf of Saxony
Rolf of Saxony

Reputation: 22433

Tart it up a bit furas! and no this answer should not be accepted as it is ripping off Furas to whom any credit should go. Rolf

#!/usr/bin/env python

import wx
import datetime

class AFrame(wx.Frame):

    def __init__ (self):
        wx.Frame.__init__(self, parent=None, id=-1, title="Countdown to Christmas", size=(400, 400))

        # 2015.12.25 1:00:00
        self.future_time = datetime.datetime(2015, 12, 25, 1, 0, 0)

        # create timer
        self.timer = wx.Timer(self)
        # assign draw_image to timer
        self.Bind(wx.EVT_TIMER, self.draw_image, self.timer)
        # start timer 
        self.timer.Start(1000)

        self.statbmp = wx.StaticBitmap(self)
        self.draw_image()
        self.Refresh()

        self.Show()

    def draw_image(self, event=None): # event required by timer

        # get deltatime
        secondsLeft = self.future_time - datetime.datetime.now()

        # get seconds, round to integer, 
        secondsLeft = int(secondsLeft.total_seconds())

        if secondsLeft <= 0:
            secondsLeft = 0
            if self.timer.IsRunning():
                self.timer.Stop()

        # convert to text
        d, s = divmod(secondsLeft,86400)
        h, s = divmod(s,3600)
        m, s = divmod(s, 60)
        timestamp = 30*"  "
        if d> 0:
            time_stamp = "%02d Days Hrs:%02d Mins:%02d Secs:%02d" % (d,h,m,s)
        elif h > 0:
            time_stamp = "Hrs:%02d Mins:%02d Secs:%02d" % (h,m,s)
        else:
            time_stamp = "Mins:%02d Secs:%02d" % (m,s)
        # select the width and height of the blank bitmap
        # must fit frame
        w, h = 400, 400

        # create the blank bitmap as background
        draw_bmp = wx.EmptyBitmap(w, h)

        #create canvas.
        canvas = wx.MemoryDC(draw_bmp)
        #fill the canvas with white
        canvas.SetBrush(wx.Brush('white'))
        canvas.Clear()

        #get text dimentions.
        tw, th = canvas.GetTextExtent(time_stamp)

        #draw the text.
        canvas.DrawText(time_stamp, (w - tw) / 2, (h - th) / 2 )

        self.statbmp.SetBitmap(draw_bmp)

app = wx.App()
AFrame()
app.MainLoop()

Upvotes: 1

furas
furas

Reputation: 142631

Use wx.Timer to run function every 1000ms (1s).

Use datetime (and deltatime) to get left seconds.

#!/usr/bin/env python

import wx
import datetime

class AFrame(wx.Frame):

    def __init__ (self):
        wx.Frame.__init__(self, parent=None, id=-1, title="Coundown to Christmas", size=(400, 400))

        # 2015.12.25 1:00:00
        self.future_time = datetime.datetime(2015, 12, 25, 1, 0, 0)

        # create timer
        self.timer = wx.Timer(self)
        # assign draw_image to timer
        self.Bind(wx.EVT_TIMER, self.draw_image, self.timer)
        # start timer 
        self.timer.Start(1000)

        self.statbmp = wx.StaticBitmap(self)
        self.draw_image()
        self.Refresh()

        self.Show()

    def draw_image(self, event=None): # event required by timer

        # get deltatime
        secondsLeft = self.future_time - datetime.datetime.now()

        # get seconds, round to integer, 
        secondsLeft = int(secondsLeft.total_seconds())

        if secondsLeft <= 0:
            secondsLeft = 0
            if self.timer.IsRunning():
                self.timer.Stop()

        # convert to text
        secondsLeft = str(secondsLeft)

        # select the width and height of the blank bitmap
        # must fit frame
        w, h = 400, 400

        # create the blank bitmap as background
        draw_bmp = wx.EmptyBitmap(w, h)

        #create canvas.
        canvas = wx.MemoryDC(draw_bmp)
        #fill the canvas with white
        canvas.SetBrush(wx.Brush('white'))
        canvas.Clear()

        #get text dimentions.
        tw, th = canvas.GetTextExtent(secondsLeft)

        #draw the text.
        canvas.DrawText(secondsLeft, (w - tw) / 2, (h - th) / 2 )

        self.statbmp.SetBitmap(draw_bmp)

app = wx.App()
AFrame()
app.MainLoop()

Upvotes: 1

Related Questions