Пример #1
0
class Canvas(Surface, MouseWheelHandler):

    def __init__(self, size, buffered):
        Surface.__init__(self, size)
        MouseWheelHandler.__init__(self, True)
        if isinstance(buffered, bool):
            self._bufferedimage = buffered
        else:
            self._bufferedimage = True
        try:
            if self.impl.canvasContext:
                self._isCanvas = True
        except:
            self._isCanvas = False
            self._bufferedimage = False
        if self._bufferedimage:
            self.surface = Surface(size)
        else:
            self.surface = self
        self.images = {}
        self.image_list = []
        self.callback = None
        self.time = Time()
        self.event = pyjsdl.event
        self.addMouseListener(self)
        self.addMouseWheelListener(self)
        self.addKeyboardListener(self)
        self.sinkEvents(Event.ONMOUSEDOWN | Event.ONMOUSEUP| Event.ONMOUSEMOVE | Event.ONMOUSEOUT | Event.ONMOUSEWHEEL | Event.ONKEYDOWN | Event.ONKEYPRESS | Event.ONKEYUP)
        self.modKey = pyjsdl.event.modKey
        self.specialKey = pyjsdl.event.specialKey
        self._repaint = False
        self._rect_list = []
        self._rect_len = 0
        self._rect_num = 0
        self._framerate = 0
        self._frametime = 0
        self._canvas_init()
        self.initialized = False

    def _canvas_init(self):
        global _canvas, _ctx, _img, _wnd
        _canvas = self
        _ctx = self.impl.canvasContext
        _img = self.surface.canvas
        _wnd = requestAnimationFrameInit()

    def onMouseMove(self, sender, x, y):
        event = DOM.eventGetCurrentEvent()
        event.pos = (x, y)
        self.event.mouseMove['x'], self.event.mouseMove['y'] = x, y
        self.event._updateQueue(event)

    def onMouseDown(self, sender, x, y):
        event = DOM.eventGetCurrentEvent()
        event.pos = (x, y)
        self.event.mousePress[event.button] = True
        self.event._updateQueue(event)

    def onMouseUp(self, sender, x, y):
        event = DOM.eventGetCurrentEvent()
        event.pos = (x, y)
        self.event.mousePress[event.button] = False
        self.event._updateQueue(event)

    def onMouseLeave(self, sender):
        self.event.mousePress[0], self.event.mousePress[1], self.event.mousePress[2] = False, False, False
        self.event.mouseMove['x'], self.event.mouseMove['y'] = -1, -1
        self.event.mouseMoveRel['x'], self.event.mouseMoveRel['y'] = None, None
        for keycode in self.modKey:
            if self.event.keyPress[keycode]:
                self.event.keyPress[keycode] = False

    def onMouseWheel(self, sender, velocity):
        event = DOM.eventGetCurrentEvent()
        if event.type == 'mousewheel':
            #TODO: update for changes in mousewheel implementation
            if hasattr(event, 'wheelDeltaX'):
                self.onMouseWheel = self._onMouseWheel
                self._onMouseWheel(sender, velocity)
            else:
                self.onMouseWheel = self._onMouseWheelY
                DOM.eventGetMouseWheelVelocityY = eventGetMouseWheelVelocityY
                self._onMouseWheelY(sender, eventGetMouseWheelVelocityY(event))
        else:       #DOMMouseScroll
            self.onMouseWheel = self._onMouseScroll
            self._onMouseScroll(sender, velocity)

    def _onMouseWheel(self, sender, velocity):
        event = DOM.eventGetCurrentEvent()
        if not event.wheelDeltaX:
            if velocity < 0:
                button = 4
                events = velocity / -3
            else:
                button = 5
                events = velocity / 3
        else:
            if velocity < 0:
                button = 6
                events = velocity / -3
            else:
                button = 7
                events = velocity / 3
        event.btn = button
        event.pos = (self.event.mouseMove['x'], self.event.mouseMove['y'])
        for evt in range(events):
            self.event._updateQueue(event)

    def _onMouseWheelY(self, sender, velocity):
        event = DOM.eventGetCurrentEvent()
        if velocity < 0:
            button = 4
            events = velocity / -3
        else:
            button = 5
            events = velocity / 3
        event.btn = button
        event.pos = (self.event.mouseMove['x'], self.event.mouseMove['y'])
        for evt in range(events):
            self.event._updateQueue(event)

    def _onMouseScroll(self, sender, velocity):
        event = DOM.eventGetCurrentEvent()
        if velocity > 1 or velocity < -1:
            if velocity < 0:
                button = 4
            else:
                button = 5
        else:
            if velocity < 0:
                button = 6
            else:
                button = 7
        event.btn = button
        event.pos = (self.event.mouseMove['x'], self.event.mouseMove['y'])
        self.event._updateQueue(event)

    def onKeyDown(self, sender, keycode, modifiers):
        if keycode in self.modKey:
            event = DOM.eventGetCurrentEvent()
            self.event.keyPress[keycode] = True
            self.event._updateQueue(event)
            DOM.eventPreventDefault(event)
        elif keycode in self.specialKey:
            event = DOM.eventGetCurrentEvent()
            self.event._updateQueue(event)
            DOM.eventPreventDefault(event)

    def onKeyPress(self, sender, keycode, modifiers):
        event = DOM.eventGetCurrentEvent()
        if not (event.keyCode and event.keyCode in self.specialKey):
            self.event._updateQueue(event)
        DOM.eventPreventDefault(event)

    def onKeyUp(self, sender, keycode, modifiers):
        event = DOM.eventGetCurrentEvent()
        if keycode in self.modKey:
            self.event.keyPress[keycode] = False
        self.event._updateQueue(event)

    def resize(self, width, height):
        Surface.resize(self, width, height)
        if self._bufferedimage:
            self.surface.resize(width, height)
        self.surface._display._surface_rect = self.surface.get_rect()

    def set_callback(self, cb):
        if not hasattr(cb, 'run'):
            self.callback = Callback(cb)
        else:
            self.callback = cb

    def load_images(self, images):
        if images:
            image_list = []
            for image in images:
                if isinstance(image, str):
                    image_list.append(image)
                    self.image_list.append(image)
                else:
                    name = image[0]
                    if isinstance(image[1], str):
                        data = image[1]
                    else:
                        data = base64.b64encode(image[1].getvalue())
                    if not data.startswith('data:'):
                        ext = name.strip().split('.')[-1]
                        data = "data:%s;base64,%s" %(ext, data)
                        #data:[<mediatype>][;base64],<data>
                    image_list.append(data)
                    self.image_list.append(name)
            loadImages(image_list, self)
        else:
            self.start()

    def onImagesLoaded(self, images):
        for i, image in enumerate(self.image_list):
            self.images[image] = images[i].getElement()
        self.start()

    def start(self):
        if not self.initialized:
            self.initialized = True
            _wnd.requestAnimationFrame(run)
            self.time.timeout(0, self)

    def stop(self):
        global run
        run = lambda ts: None
        self.run = lambda: None

    def _get_rect(self):
        if self._rect_num < self._rect_len:
            return self._rect_list[self._rect_num]
        else:
            self._rect_list.append(Rect(0,0,0,0))
            self._rect_len += 1
            return self._rect_list[self._rect_num]

    def run(self):
        if not self._repaint:
            self.callback.run()
            self._repaint = True
        self.time.timeout(0, self)
Пример #2
0
class Canvas(Surface, MouseWheelHandler):
    def __init__(self, size, buffered):
        Surface.__init__(self, size)
        MouseWheelHandler.__init__(self, True)
        if isinstance(buffered, bool):
            self._bufferedimage = buffered
        else:
            self._bufferedimage = True
        try:
            if self.impl.canvasContext:
                self._isCanvas = True
        except:
            self._isCanvas = False
            self._bufferedimage = False
        if self._bufferedimage:
            self.surface = Surface(size)
        else:
            self.surface = self
        self.images = {}
        self.image_list = []
        self.callback = None
        self.time = Time()
        self.event = pyjsdl.event
        self.addMouseListener(self)
        self.addMouseWheelListener(self)
        self.addKeyboardListener(self)
        self.sinkEvents(Event.ONMOUSEDOWN | Event.ONMOUSEUP | Event.ONMOUSEMOVE
                        | Event.ONMOUSEOUT | Event.ONMOUSEWHEEL
                        | Event.ONKEYDOWN | Event.ONKEYPRESS | Event.ONKEYUP)
        self.modKey = pyjsdl.event.modKey
        self.specialKey = pyjsdl.event.specialKey
        self.event._initiate_touch_listener(self)
        self._touch_callback = self.event.touchlistener.callback
        self._repaint = False
        self._rect_list = []
        self._rect_len = 0
        self._rect_num = 0
        self._framerate = 0
        self._frametime = 0
        self._canvas_init()
        self.initialized = False

    def _canvas_init(self):
        global _canvas, _ctx, _img, _wnd
        _canvas = self
        _ctx = self.impl.canvasContext
        _img = self.surface.canvas
        _wnd = requestAnimationFrameInit()

    def onMouseMove(self, sender, x, y):
        event = DOM.eventGetCurrentEvent()
        event.pos = (x, y)
        self.event.mouseMove['x'], self.event.mouseMove['y'] = x, y
        self.event._updateQueue(event)

    def onMouseDown(self, sender, x, y):
        event = DOM.eventGetCurrentEvent()
        event.pos = (x, y)
        self.event.mousePress[event.button] = True
        self.event._updateQueue(event)

    def onMouseUp(self, sender, x, y):
        event = DOM.eventGetCurrentEvent()
        event.pos = (x, y)
        self.event.mousePress[event.button] = False
        self.event._updateQueue(event)

    def onMouseLeave(self, sender):
        self.event.mousePress[0], self.event.mousePress[
            1], self.event.mousePress[2] = False, False, False
        self.event.mouseMove['x'], self.event.mouseMove['y'] = -1, -1
        self.event.mouseMoveRel['x'], self.event.mouseMoveRel['y'] = None, None
        for keycode in self.modKey:
            if self.event.keyPress[keycode]:
                self.event.keyPress[keycode] = False

    def onMouseWheel(self, sender, velocity):
        event = DOM.eventGetCurrentEvent()
        if event.type == 'mousewheel':
            #TODO: update for changes in mousewheel implementation
            if hasattr(event, 'wheelDeltaX'):
                self.onMouseWheel = self._onMouseWheel
                self._onMouseWheel(sender, velocity)
            else:
                self.onMouseWheel = self._onMouseWheelY
                DOM.eventGetMouseWheelVelocityY = eventGetMouseWheelVelocityY
                self._onMouseWheelY(sender, eventGetMouseWheelVelocityY(event))
        else:  #DOMMouseScroll
            self.onMouseWheel = self._onMouseScroll
            self._onMouseScroll(sender, velocity)

    def _onMouseWheel(self, sender, velocity):
        event = DOM.eventGetCurrentEvent()
        if not event.wheelDeltaX:
            if velocity < 0:
                button = 4
                events = velocity / -3
            else:
                button = 5
                events = velocity / 3
        else:
            if velocity < 0:
                button = 6
                events = velocity / -3
            else:
                button = 7
                events = velocity / 3
        event.btn = button
        event.pos = (self.event.mouseMove['x'], self.event.mouseMove['y'])
        for evt in range(events):
            self.event._updateQueue(event)

    def _onMouseWheelY(self, sender, velocity):
        event = DOM.eventGetCurrentEvent()
        if velocity < 0:
            button = 4
            events = velocity / -3
        else:
            button = 5
            events = velocity / 3
        event.btn = button
        event.pos = (self.event.mouseMove['x'], self.event.mouseMove['y'])
        for evt in range(events):
            self.event._updateQueue(event)

    def _onMouseScroll(self, sender, velocity):
        event = DOM.eventGetCurrentEvent()
        if velocity > 1 or velocity < -1:
            if velocity < 0:
                button = 4
            else:
                button = 5
        else:
            if velocity < 0:
                button = 6
            else:
                button = 7
        event.btn = button
        event.pos = (self.event.mouseMove['x'], self.event.mouseMove['y'])
        self.event._updateQueue(event)

    def onKeyDown(self, sender, keycode, modifiers):
        if keycode in self.modKey:
            event = DOM.eventGetCurrentEvent()
            self.event.keyPress[keycode] = True
            self.event._updateQueue(event)
            DOM.eventPreventDefault(event)
        elif keycode in self.specialKey:
            event = DOM.eventGetCurrentEvent()
            self.event._updateQueue(event)
            DOM.eventPreventDefault(event)

    def onKeyPress(self, sender, keycode, modifiers):
        event = DOM.eventGetCurrentEvent()
        if not (event.keyCode and event.keyCode in self.specialKey):
            self.event._updateQueue(event)
        DOM.eventPreventDefault(event)

    def onKeyUp(self, sender, keycode, modifiers):
        event = DOM.eventGetCurrentEvent()
        if keycode in self.modKey:
            self.event.keyPress[keycode] = False
        self.event._updateQueue(event)

    def onTouchInitiate(self, event):
        self.event.touchlistener.activate()
        for callback in self._touch_callback:
            if hasattr(callback, 'onTouchInitiate'):
                callback.onTouchInitiate(event)
        self.onTouchStart(event)

    def onTouchStart(self, event):
        for callback in self._touch_callback:
            callback.onTouchStart(event)

    def onTouchEnd(self, event):
        for callback in self._touch_callback:
            callback.onTouchEnd(event)

    def onTouchMove(self, event):
        for callback in self._touch_callback:
            callback.onTouchMove(event)

    def onTouchCancel(self, event):
        for callback in self._touch_callback:
            callback.onTouchCancel(event)

    def resize(self, width, height):
        Surface.resize(self, width, height)
        if self._bufferedimage:
            self.surface.resize(width, height)
        self.surface._display._surface_rect = self.surface.get_rect()

    def set_callback(self, cb):
        if not hasattr(cb, 'run'):
            self.callback = Callback(cb)
        else:
            self.callback = cb

    def load_images(self, images):
        if images:
            image_list = []
            for image in images:
                if isinstance(image, str):
                    image_list.append(image)
                    self.image_list.append(image)
                else:
                    name = image[0]
                    if isinstance(image[1], str):
                        data = image[1]
                    else:
                        data = base64.b64encode(image[1].getvalue())
                    if not data.startswith('data:'):
                        ext = name.strip().split('.')[-1]
                        data = "data:%s;base64,%s" % (ext, data)
                        #data:[<mediatype>][;base64],<data>
                    image_list.append(data)
                    self.image_list.append(name)
            loadImages(image_list, self)
        else:
            self.start()

    def onImagesLoaded(self, images):
        for i, image in enumerate(self.image_list):
            self.images[image] = images[i].getElement()
        self.start()

    def start(self):
        if not self.initialized:
            self.initialized = True
            _wnd.requestAnimationFrame(run)
            self.time.timeout(0, self)

    def stop(self):
        global run
        run = lambda ts: None
        self.run = lambda: None

    def _get_rect(self):
        if self._rect_num < self._rect_len:
            return self._rect_list[self._rect_num]
        else:
            self._rect_list.append(Rect(0, 0, 0, 0))
            self._rect_len += 1
            return self._rect_list[self._rect_num]

    def run(self):
        if not self._repaint:
            self.callback.run()
            self._repaint = True
        self.time.timeout(0, self)
Пример #3
0
class Canvas(Surface):
    def __init__(self, size, buffered):
        Surface.__init__(self, size)
        if isinstance(buffered, bool):
            self._bufferedimage = buffered
        else:
            self._bufferedimage = True
        try:
            if self.impl.canvasContext:
                self._isCanvas = True
        except:
            self._isCanvas = False
            self._bufferedimage = False
        if self._bufferedimage:
            self.surface = Surface(size)
        else:
            self.surface = self
        self.images = {}
        self.image_list = []
        self.callback = None
        self.time = Time()
        self.event = env.event
        self.addMouseListener(self)
        self.addKeyEventListener(self)
        self.sinkEvents(Event.ONMOUSEDOWN | Event.ONMOUSEUP | Event.ONMOUSEMOVE
                        | Event.ONMOUSEOUT | Event.ONMOUSEWHEEL
                        | Event.ONKEYDOWN | Event.ONKEYPRESS | Event.ONKEYUP)
        self.onContextMenu = None
        self.preventContextMenu()
        self.evt = self.event.eventObj
        self.modKey = self.event.modKey
        self.specialKey = self.event.specialKey
        self.modKeyCode = self.event.modKeyCode
        self.specialKeyCode = self.event.specialKeyCode
        self.keyRepeat = self.event.keyRepeat
        self.keyHeld = self.event.keyHeld
        self.mouse_entered = True
        self.event._initiate_touch_listener(self)
        self._touch_callback = self.event.touchlistener.callback
        self._rect_list = []
        self._rect_len = 0
        self._rect_num = 0
        self._framerate = 0
        self._frametime = 0
        self._rendertime = self.time.time()
        self._pause = False
        self._canvas_init()
        self.initialized = False

    def _canvas_init(self):
        global _canvas, _ctx, _img, _wnd
        _canvas = self
        _ctx = self.impl.canvasContext
        _img = self.surface.canvas
        _wnd = requestAnimationFrameInit()

    def onMouseMove(self, sender, x, y):
        event = DOM.eventGetCurrentEvent()
        if event.type in self.event.events:
            if not self.mouse_entered:
                self.event.mouseMovePre['x'] = self.event.mouseMove['x']
                self.event.mouseMovePre['y'] = self.event.mouseMove['y']
            else:
                self.event.mouseMovePre['x'] = x
                self.event.mouseMovePre['y'] = y
                self.mouse_entered = False
            self.event._updateQueue(self.evt[event.type](event, x, y))
        self.event.mouseMove['x'] = x
        self.event.mouseMove['y'] = y

    def onMouseDown(self, sender, x, y):
        event = DOM.eventGetCurrentEvent()
        if event.type in self.event.events:
            self.event._updateQueue(self.evt[event.type](event, x, y))
        self.event.mousePress[event.button] = True

    def onMouseUp(self, sender, x, y):
        event = DOM.eventGetCurrentEvent()
        if event.type in self.event.events:
            self.event._updateQueue(self.evt[event.type](event, x, y))
        self.event.mousePress[event.button] = False

    def onMouseEnter(self, sender):
        self.mouse_entered = True

    def onMouseLeave(self, sender):
        self.event.mousePress[0] = False
        self.event.mousePress[1] = False
        self.event.mousePress[2] = False
        self.event.mouseMove['x'] = -1
        self.event.mouseMove['y'] = -1
        self.event.mouseMoveRel['x'] = None
        self.event.mouseMoveRel['y'] = None
        for keycode in self.modKeyCode:
            if self.event.keyPress[keycode]:
                self.event.keyPress[keycode] = False

    def onMouseWheel(self, event):
        if event.type in self.event.events:
            r = self.canvas.getBoundingClientRect()
            x = event.clientX - round(r.left)
            y = event.clientY - round(r.top)
            self.event._updateQueue(self.evt[event.type](event, x, y))
        DOM.eventPreventDefault(event)

    def onKeyEvent(self, event):
        self.removeKeyEventListener(self)
        self.addKeyboardListener(self)
        DOM.currentEvent = event
        if hasattr(event, 'key') and hasattr(event, 'code'):
            self.onKeyDown(self, event.key, 0)
        else:
            self.event._set_key_event()
            self.onKeyDown = self._onKeyDown
            self.onKeyUp = self._onKeyUp
            self.onKeyPress = self._onKeyPress
            keycode = event.which or event.keyCode or 0
            self._onKeyDown(self, keycode, 0)

    def onKeyDown(self, sender, keycode, mods):
        event = DOM.eventGetCurrentEvent()
        if event.key in self.modKey:
            self.event.keyPress[self.modKey[event.key]] = True
        if event.type in self.event.events:
            if not self._isPaused(event.key):
                self.event._updateQueue(self.evt[event.type](event))
        DOM.eventPreventDefault(event)

    def onKeyUp(self, sender, keycode, mods):
        event = DOM.eventGetCurrentEvent()
        if event.key in self.modKey:
            self.event.keyPress[self.modKey[event.key]] = False
        if event.key in self.keyHeld:
            self.keyHeld[event.key]['pressed'] = False
        if event.type in self.event.events:
            self.event._updateQueue(self.evt[event.type](event))

    def _onKeyDown(self, sender, keycode, mods):
        event = DOM.eventGetCurrentEvent()
        if keycode in self.modKeyCode:
            self.event.keyPress[keycode] = True
        if event.type in self.event.events:
            if not self._isPaused(keycode):
                self.event.keyCode = keycode
                if keycode in self.specialKeyCode:
                    self.event._updateQueue(self.evt[event.type](event,
                                                                 keycode))
                    DOM.eventPreventDefault(event)
            else:
                DOM.eventPreventDefault(event)

    def _onKeyUp(self, sender, keycode, mods):
        event = DOM.eventGetCurrentEvent()
        if keycode in self.modKeyCode:
            self.event.keyPress[keycode] = False
        if keycode in self.keyHeld:
            self.keyHeld[keycode]['pressed'] = False
        if event.type in self.event.events:
            self.event._updateQueue(self.evt[event.type](event, keycode))

    def _onKeyPress(self, sender, keycode, mods):
        event = DOM.eventGetCurrentEvent()
        if event.type in self.event.events:
            self.event.keyPressCode[self.event.keyCode] = keycode
            self.event._updateQueue(self.evt[event.type](event, keycode))
        event.preventDefault()

    def _isPaused(self, keycode):
        if keycode not in self.keyHeld:
            self.keyHeld[keycode] = {
                'pressed': False,
                'delay': False,
                'time': 0
            }
        key = self.keyHeld[keycode]
        if not key['pressed']:
            key['pressed'] = True
            paused = False
            if self.keyRepeat[0]:
                key['delay'] = True
                key['time'] = self.time.time()
        else:
            paused = True
            if self.keyRepeat[0]:
                time = self.time.time()
                if key['delay']:
                    if time - key['time'] > self.keyRepeat[0]:
                        key['time'] = time
                        key['delay'] = False
                        paused = False
                elif time - key['time'] > self.keyRepeat[1]:
                    key['time'] = time
                    paused = False
        return paused

    def onTouchInitiate(self, event):
        self.event.touchlistener.activate()
        for callback in self._touch_callback:
            if hasattr(callback, 'onTouchInitiate'):
                callback.onTouchInitiate(event)
        self.onTouchStart(event)

    def onTouchStart(self, event):
        for callback in self._touch_callback:
            callback.onTouchStart(event)

    def onTouchEnd(self, event):
        for callback in self._touch_callback:
            callback.onTouchEnd(event)

    def onTouchMove(self, event):
        for callback in self._touch_callback:
            callback.onTouchMove(event)

    def onTouchCancel(self, event):
        for callback in self._touch_callback:
            callback.onTouchCancel(event)

    def preventContextMenu(self, setting=True):
        """
        Control contextmenu event.
        Optional bool setting to prevent event, default to True.
        """
        if setting:
            if self.onContextMenu: return
            element = self.getElement()
            self.onContextMenu = lambda event: event.preventDefault()
            element.addEventListener('contextmenu', self.onContextMenu)
        else:
            if not self.onContextMenu: return
            element = self.getElement()
            element.removeEventListener('contextmenu', self.onContextMenu)
            self.onContextMenu = None

    def resize(self, width, height):
        Surface.resize(self, width, height)
        if self._bufferedimage:
            self.surface.resize(width, height)
        self.surface._display._surface_rect = self.surface.get_rect()

    def set_callback(self, cb):
        if not hasattr(cb, 'run'):
            self.callback = Callback(cb)
        else:
            self.callback = cb

    def load_images(self, images):
        if images:
            image_list = []
            for image in images:
                if isinstance(image, str):
                    image_list.append(image)
                    self.image_list.append(image)
                else:
                    name = image[0]
                    if isinstance(image[1], str):
                        data = image[1]
                    else:
                        data = base64.b64encode(image[1].getvalue())
                    if not data.startswith('data:'):
                        ext = name.strip().split('.')[-1]
                        data = "data:%s;base64,%s" % (ext, data)
                        #data:[<mediatype>][;base64],<data>
                    image_list.append(data)
                    self.image_list.append(name)
            loadImages(image_list, self)
        else:
            self.start()

    def onImagesLoaded(self, images):
        for i, image in enumerate(self.image_list):
            self.images[image] = images[i].getElement()
        self.start()

    def start(self):
        if not self.initialized:
            self.initialized = True
            _wnd.requestAnimationFrame(run)

    def stop(self):
        global run
        run = lambda ts: None
        self.run = lambda: None

    def _get_rect(self):
        if self._rect_num < self._rect_len:
            return self._rect_list[self._rect_num]
        else:
            self._rect_list.append(Rect(0, 0, 0, 0))
            self._rect_len += 1
            return self._rect_list[self._rect_num]

    def update(self, timestamp):
        if not self._framerate:
            self._frametime = timestamp - self._rendertime
            self.run()
        else:
            self._frametime += timestamp - self._rendertime
            if self._frametime > self._framerate:
                self.run()
                self._frametime = 0
        self._rendertime = timestamp

    def render(self):
        while self._rect_num:
            rect = self._rect_list[self._rect_num - 1]
            x, y, width, height = rect.x, rect.y, rect.width, rect.height
            _ctx.drawImage(_img, x, y, width, height, x, y, width, height)
            self._rect_num -= 1

    def run(self):
        self.callback.run()