-
-
Save itzexor/b1093d447648397b061f9d54dcfe7d78 to your computer and use it in GitHub Desktop.
Simple dearpygui test app that tries to run at low fps when user is not interacting
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/python | |
| from collections import deque | |
| from threading import Thread | |
| from time import perf_counter as get_time | |
| from sched import Event, scheduler | |
| import stats | |
| import dearpygui.dearpygui as dpg | |
| FPS = 60 | |
| IDLE_FPS = 6 | |
| IDLE_TIMEOUT = 5 | |
| DATA_UPDATE_INTERVAL = 1 | |
| TPS = 1 | |
| FRAME_TIMING = TPS / FPS | |
| IDLE_FRAME_TIMING = TPS / IDLE_FPS | |
| class TimerObject(): | |
| event_id = 0 | |
| interval = 0 | |
| callback = None | |
| args = None | |
| def __init__(self, interval, callback, args) -> None: | |
| self.interval = interval | |
| self.callback = callback | |
| self.args = args | |
| class DpgApp: | |
| _idle_info = (0, 0, 0) | |
| _is_idle = False | |
| _render_time = 0 | |
| _render_event = None | |
| _mainloop = scheduler(timefunc=get_time) | |
| _ui_queue = deque() | |
| _timers = {} | |
| _next_timer_id = 0 | |
| def __init__(self, window_title="") -> None: | |
| dpg.create_context() | |
| dpg.setup_dearpygui() | |
| dpg.create_viewport(title=window_title) | |
| dpg.set_viewport_vsync(False) | |
| stats.init() | |
| dpg.show_metrics() | |
| def _process_ui_queue(self) -> None: | |
| while len(self._ui_queue): | |
| d = self._ui_queue.popleft() | |
| dpg.set_value(item=d[0], value=f'{d[1]:0.3}') | |
| def _render(self) -> None: | |
| if not dpg.is_dearpygui_running(): | |
| return | |
| self._render_event = None | |
| self._process_ui_queue() | |
| dpg.render_dearpygui_frame() | |
| self._check_idle() | |
| self._queue_render() | |
| def _queue_render(self, force_active=False) -> None: | |
| if not force_active and self._is_idle: | |
| delay = IDLE_FRAME_TIMING | |
| else: | |
| delay = FRAME_TIMING | |
| next = self._next_render_time + delay | |
| if self._render_event: | |
| self._mainloop.cancel(self._render_event) | |
| self._next_render_time = next | |
| self._render_event = self.queue_event(self._render, time=next, priority=0) | |
| def _check_idle(self) -> None: | |
| (x1, y1, t) = self._idle_info | |
| (x2, y2) = dpg.get_mouse_pos(local=False) | |
| if x1 != x2 or y1 != y2: | |
| self._idle_info = (x2, y2, get_time()) | |
| self._is_idle = False | |
| elif get_time() - t > IDLE_TIMEOUT: | |
| self._is_idle = True | |
| @property | |
| def is_idle(self) -> bool: | |
| return self._is_idle | |
| def _run_threads(self) -> None: | |
| Thread(target=stats.run, args=[self]).start() | |
| def _run_timer(self, id) -> None: | |
| t = self._timers[id] | |
| t.callback(*t.args) | |
| t.event_id = self.queue_event(callback=self._run_timer, args=[id], delay=t.interval) | |
| def queue_render(self) -> None: | |
| self._queue_render(force_active=True) | |
| def queue_event(self, callback, args=[], kwargs={}, delay=0, time=None, priority=100) -> Event: | |
| if not dpg.is_dearpygui_running(): | |
| return | |
| if time: | |
| return self._mainloop.enterabs(time, priority, callback, args, kwargs) | |
| return self._mainloop.enter(delay, priority, callback, args, kwargs) | |
| def cancel_event(self, event) -> bool: | |
| try: | |
| self._mainloop.cancel(event) | |
| except ValueError: | |
| return False | |
| return True | |
| def start_timer(self, interval, callback, args=[]) -> str: | |
| self._next_timer_id += 1 | |
| t = TimerObject(interval, callback, args) | |
| self._timers[self._next_timer_id] = t | |
| t.event_id = self.queue_event(callback=self._run_timer, args=[self._next_timer_id], delay=interval) | |
| return self._next_timer_id | |
| def stop_timer(self, id) -> bool: | |
| t = self._timers[id] | |
| self.cancel_event(t.event_id) | |
| del self._timers[id] | |
| def run(self) -> None: | |
| self._last_active_time = self._next_render_time = get_time() | |
| self._queue_render() | |
| dpg.show_viewport() | |
| self._is_running = True | |
| self.start_timer(DATA_UPDATE_INTERVAL * TPS, self._run_threads) | |
| self._mainloop.run() | |
| if __name__ == "__main__": | |
| app = DpgApp("Test App") | |
| app.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment