Last active
March 27, 2022 17:39
-
-
Save Willy-JL/6f58dda1f6953c5be85880e0cb052602 to your computer and use it in GitHub Desktop.
PyImGui + Aiohttp example, with main sync thread for window and second thread for asyncio
This file contains 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
from imgui.integrations.glfw import GlfwRenderer | |
import OpenGL.GL as gl | |
import traceback | |
import threading | |
import asyncio | |
import aiohttp | |
import imgui | |
import glfw | |
import sys | |
url = "https://google.com/" | |
html = "" | |
async def fetch_url(): | |
global url, html | |
html = "" | |
try: | |
async with aiohttp.ClientSession() as cs: | |
async with cs.get(url) as req: | |
html = await req.text() | |
except Exception: | |
html = "The request failed:\n" + "".join(traceback.format_exception(*sys.exc_info())) | |
def impl_glfw_init(): | |
# This initializes the window backend | |
# No need to understand this function | |
# Taken from https://github.com/pyimgui/pyimgui/blob/master/doc/examples/integrations_glfw3.py | |
width, height = 560, 680 | |
window_name = "PyImGui Aiohttp Example" | |
if not glfw.init(): | |
print("Could not initialize OpenGL context") | |
sys.exit(1) | |
# OS X supports only forward-compatible core profiles from 3.2 | |
glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3) | |
glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3) | |
glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE) | |
glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, gl.GL_TRUE) | |
# Create a windowed mode window and its OpenGL context | |
window = glfw.create_window(int(width), int(height), window_name, None, None) | |
glfw.make_context_current(window) | |
if not window: | |
glfw.terminate() | |
print("Could not initialize Window") | |
sys.exit(1) | |
return window | |
def main(): | |
global url, html | |
# Setup window: | |
imgui.create_context() | |
window = impl_glfw_init() | |
impl = GlfwRenderer(window) | |
while not glfw.window_should_close(window): | |
# Process events and inputs, so GUI is responsive: | |
glfw.poll_events() | |
impl.process_inputs() | |
imgui.new_frame() | |
# Your actual code for the window goes here | |
# Setup main fullscreen window: | |
imgui.set_next_window_position(0, 0) | |
imgui.set_next_window_size(*impl.io.display_size, imgui.ALWAYS) | |
with imgui.begin( | |
# All ImGui widgets and items need to have labels. You cannot have "". Prefix with ## to hide them: | |
"##Main Window", | |
flags=( | |
imgui.WINDOW_NO_MOVE | | |
imgui.WINDOW_NO_RESIZE | | |
imgui.WINDOW_NO_COLLAPSE | | |
imgui.WINDOW_NO_TITLE_BAR | | |
imgui.WINDOW_NO_SAVED_SETTINGS | | |
imgui.WINDOW_HORIZONTAL_SCROLLING_BAR | |
) | |
): | |
# Main window content | |
# The render loop runs every frame. Because of this you give widgets their initial value and they | |
# give back their new value. Many widgets return two things: a bool for whether the value changed | |
# this frame, and the actual new value: | |
url_changed, url = imgui.input_text("##URL", url, 999) | |
# By default each widget is on its own line. This sets the render cursor to stay on the same line. | |
# You can also do imgui.same_line(123) to set the horizontal position of the next element: | |
imgui.same_line() | |
# Buttons return one thing: whether they were pressed or not in this frame. This makes adding | |
# callbacks to them as easy as putting them in an if check: | |
if imgui.button("Fetch!"): | |
# Run async coroutine in separate async thread: | |
asyncio.run_coroutine_threadsafe(fetch_url(), loop) | |
# Render the html as plain text: | |
imgui.text(html) | |
# Clear previous frame and add background color: | |
gl.glClearColor(0.0, 0.0, 0.0, 1) | |
gl.glClear(gl.GL_COLOR_BUFFER_BIT) | |
# Render and show the new frame: | |
imgui.render() | |
impl.render(imgui.get_draw_data()) | |
glfw.swap_buffers(window) | |
# Cleanup: | |
impl.shutdown() | |
glfw.terminate() | |
if __name__ == "__main__": | |
# Setup async loop in separate thread: | |
loop = asyncio.new_event_loop() | |
threading.Thread(target=lambda: [asyncio.set_event_loop(loop), loop.run_forever()], daemon=True).start() | |
# Start ImGui render loop in main sync thread: | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment