10 ms·
Immediate Mode GUI Programming
- moron4hire 3y agoImmediate mode GUI is fine for quick and dirty things, but once you start dealing with multiple application views that conditionally show/hide, with branching flows of any kind, you'll find yourself on a hardline track to reinvent retained mode GUI from scratch just so you can handle the event loop in a sane way. Object oriented, event driven widgets composed into more colored views are really, really good for developing UI. There's a reason every major OS GUI toolkit is this design. If you componentize like you are supposed to--instead of just smashing everything into one form--they work and can be reasoned over with few surprises. The trouble comes from not componentizing things that you should when your current platform doesn't provide the full menagerie of widgets that you'll need. Basically, it you have any kind of input that results in a value that is not just a raw string, you should be building a component for that input: URLs, paths to files, numbers, dates, selectors for picking a set list of structured objects, etc.
- flohofwoe 3y agoIsn't the whole point of immediate mode UIs to get rid of the "event loop" though? > multiple application views that conditionally show/hide The ImGui way of doing this is to conditionally run or not run the code which describes the conditionally shown UI elements. E.g. a simple if (viewShown) { ...code which describes what the view looks like } There are plenty of real-world applications with complex UIs implemented in Dear ImGui which don't seem to have a problem with those things, e.g. see https://github.com/ocornut/imgui/labels/gallery https://github.com/ocornut/imgui/labels/gallery > The trouble comes from not componentizing things... In ImGui, reusable UI components are just code which describes the UI component by calling lower-level ImGui functions and which itself is a new ImGui-style function. It works surprisingly well.
- moron4hire 3y ago>> Isn't the whole point of immediate UIs to get rid of the "event loop" though? No, not at all. It's to take explicit control of the event loop. It's right there, you have a loop and the buttons still fire events, you just have to check for them on every iteration of the loop.
- flohofwoe 3y agoYou don't have to 'install' event handlers, there are no event objects, and there's no event loop like: while (uiEvent = uiGetNextEvent()) { uiHandleEvent(uiEvent); } ...and it would never enter my mind to call this an 'event handler': if (Button("Click Me!")) { printf("Button Clicked!"); } One very nice side effect of this immediate mode style code is that it 'runs on a linear timeline', e.g. you can step through the code in a debugger without having to put breakpoints inside 'event handlers'. How all this is implemented inside the immediate mode UI framework isn't relevant. The 'immediate mode idea' is only about the user-facing code which describes the UI, not the internal implementation (those can vastly differ, and could even manage a 'retained mode' widget tree under the hood).
- deleted 3y ago[deleted]
- epcoa 3y agoIf your entire system ran with immediate mode GUIs your performance would either be in the toilet or battery life would be destroyed (or both). They’re great for games and GPU where you’re in a for a pound anyway. There are some music apps that use it and it’s horrible if you’re on a laptop. No I don’t want to consume a couple watts when I should be idling because the entire screen is being repainted doing nothing. Makes electron seem nice.
- goodpaul6 3y agoI'm not sure the perf/battery life tradeoff is a necessary aspect of immediate mode UI. while (running) { event := get_next_event() process_event(event) repaint() } You could just have get_next_event block until there is a meaningful event that occurs (e.g. mouse click). You could even have your UI report "interactive" rectangles to the event layer to prevent it from producing e.g. mouse move events that are irrelevant. IMGUI is just a different API design IMO.
- kvemkon 3y ago> IMGUI is just a different API design IMO. There are so many issues about so called "power saving mode" and several open PRs like https://github.com/ocornut/imgui/pull/5116 https://github.com/ocornut/imgui/pull/5116.
- n2d4 3y agoIf you do that, you have an event loop again (like in the OP), which your comment's grandparent was trying to get rid of (and your parent explained to them why they can't).
- whstl 3y agoIn practice there is always a loop. I believe the point flohofwoe was making is that with an immediate UI you don't have to even touch events in your immediate UI code (they are abstracted away, if needed, in a pretty clean manner, IMO), so there's no need to do anything to get a "sane event loop". I might be wrong about what's his point though.
- jesse__ 3y agoI'm sorry, but I've got to call this out as woefully inaccurate. > [...] so you can handle the event loop in a sane way. The whole point of an immediate-mode framework is that the call-stack acts as the event loop. You run through your UI code, and if a thing was interacted with on the previous frame, you just handle it. What about that setup is not sane? > [...] instead of just smashing everything into one form [...] There is nothing about immediate mode that makes it more or less able to have everything 'smashed into one form'. You can do that just as well with your retained-mode framework of choice. > The trouble comes from not componentizing things This also has nothing to do with the immediate vs. retained mode discussion. You could just as easily make a giant mess in retained-mode by not making reusable components. > once you start dealing with multiple application views that conditionally show/hide, with branching flows of any kind [..] In my spare time, I work on a game engine whose editor/debug UI is completely immediate mode. There are discrete views into nearly everything in the engine. Entity data, a color picker, memory and CPU performance views, asset viewers/pickers, a terrain editor with like 10 modes.. you name it. There are plenty of conditionally shown views. There is plenty of 'componentizing' of things going on. The editor UI is in the neighborhood of 10k lines, most of which is generated. If that's below your bar for quick-n-dirty, maybe we have different opinions on what qualifies.
- moron4hire 3y ago>> The editor UI is in the neighborhood of 10k lines, most of which is generated. I mean, this sounds like you've created a retained mode DSL that gets compiled into immediate mode. And yes, 10 KLoC is definitely a small project, especially when "most of which is generated".
- jesse__ 3y ago> this sounds like you've created a retained mode DSL that gets compiled into immediate mode Nope, I wrote a template-metaprogramming language, which generates the UI. There's nothing retained-mode about it. The source code: https://github.com/scallyw4g/bonsai/blob/672a3520d7537ef4e754e0dc2535f2df5817c99a/src/engine/editor.h#L81 https://github.com/scallyw4g/bonsai/blob/672a3520d7537ef4e75... The result: https://github.com/scallyw4g/bonsai/blob/master/generated/do_editor_ui_for_compound_type_world_chunk.h https://github.com/scallyw4g/bonsai/blob/master/generated/do... > And yes, 10 KLoC is definitely a small project I said it cleared the bar for quick-n-dirty. I agree it's not a large amount of code.
- merb 3y ago> There's a reason every major OS GUI toolkit is this design. Ehh.. the latest os ui toolkit is uwp which lost to react native (a im gui) and it does not look that winui3 will fix that. Linux has two major gui libraries, both are probably only used by enthusiasts and not by enterprises which prefer to target react native (mostly for different reasons tough) Drawing components won because the object oriented world of gui design sucks and because it’s hard to target multiple systems. All modern ui libs use a kind of immediate mode. It’s way easier to understand and you do not need to explain why you need to use mvvm.
- jayd16 3y agoReact native is an imgui? Aren't views defined with a declarative language similar but distinct from html?
- kragen 3y agoyes, it is yes, they usually are, which is irrelevant to the question of whether react is retained-mode or immediate-mode please see https://news.ycombinator.com/item?id=39010462 https://news.ycombinator.com/item?id=39010462 for more detail
- rstat1 3y agoFor desktop use, Qt is quite widely used pretty much everywhere. I only ever see React Native being used so a company can claim to have a "native" mobile app.
- merb 3y agoIm not sure if you used windows in the last 5 years than. Heck the new outlook is a react native kind of ui.
- rstat1 3y agoAll the stuff I use on Windows (save for Discord) is a real native app. I don't use the new Outlook app because MS email apps usually suck compared to what's available elsewhere.
- jcranmer 3y agoThe way I think about it, GUIs come down to a few basic principles: 1. Program data is primarily hierarchical. This means that you can generally compose a view for a data item out of smaller views down to a basic set of elements (e.g., text display, combo box, etc.), and also means that you can generally ignore all data not included that view. There are some cases where this breaks down (tables really stretch it, for example), but it definitely holds for most GUIs. 2. UI also has state independent of program data. Immediate GUIs to a degree go ha-ha-there's-no-such-thing and make it somebody else's problem, but this state has to be retained somewhere. However, it's not exactly a binary choice between UI and program state--something like whether or not a checkbox is checked can go either way (I think of it as UI state because I tend to deal in batch-mode programs, where what is going to happen is the UI state will be distilled into the input to code I execute whose results will be displayed). 3. Conversion of program state to UI needs to be lazy--you don't want to forcibly map every element in a list immediately to UI widgets. The best example of this, of course, is the scrollbar. 4. Whereas program state is hierarchical, UI state is far less hierarchical in nature. That is to say, the state of a UI element may influence the display of a UI element in a completely different tree. The difference between immediate and retained mode is less important than it might seem at first glance. If your UI is simple and largely static, hierarchical application of canned elements, then both an immediate and a retained mode interface will end up looking roughly the same in terms of code. If your UI is complex and deals with heavy and very impure state, it again doesn't matter all that much, because you're going to have to maintain that state all yourself anyways. As a programmer who hates writing GUI code, though, all I really want is a thoroughly complete set of widgets (the ontology of UI is pretty standard, after all). I don't really care about immediate mode or retained mode, I just want a path that lets me easily render my program state with the minimum hassle. And quite frankly, it seems like the only GUI toolkits that make it as far as figuring out how to include a lazy table widget are the retained mode GUIs, which maybe suggests something about immediate mode GUIs.
- flohofwoe 3y agoTBH from looking at the code examples it looks a bit like it's halfway stuck between a traditional object-oriented UI framework, and a "proper" immediate mode UI (for instance why is there a variable that seems to be a button object).
- hsn915 3y agoYea, it's unfortunate. I also find their layout "framework"/API to be weird and counter intuitive.
- jbverschoor 3y agoImmediate mode is very common in game development. Super easy to reason about and debug.
- jheriko 3y agoi am a gamedev. i never encountered this until unity became popular, and even then it was always looked down on as a shitty and hacky approach to a well solved class of problem. 10 years after this, its still about the same... which is probably why an article like this has any controversy about it instead of being run-of-the-mill.
- TillE 3y agoAbsolutely everyone (including the AAA studios) uses Dear ImGui for tools these days. Retained mode is probably more common for user-facing GUIs, though.
- badsectoracula 3y ago> Absolutely everyone (including the AAA studios) uses Dear ImGui for tools these days. I've been working in (mostly AAA) game engines and tools since the mid-2000s, largely in custom engines and i never encountered Dear Imgui, so i disagree with the "absolutely everyone". Pretty much every engine i've worked with (and didn't make myself) uses something like wxWidgets, Qt, MFC or some custom toolkit for the tools and custom stuff for in-game debugging (usually a console for keyboard use and some "page/screen" based reporting/lists/menus that are easy to navigate with a gamepad). I do know that some game engines use it, but it isn't as universal as you think.
- flohofwoe 3y agoIf you look at 'development screenshots' of games in the last 5 years where some sort of inhouse debugging UI is visible, it's almost guaranteed to be Dear ImGui. Qt, WPF, wxWidgets etc... was a good option up until 2015 or so, but since then the least painful way for writing integrated debugging UIs and standalone inhouse UI tools is Dear ImGui.
- treyd 3y agoKinda an unfortunate name collision with GIO as used in another UI toolkit stack: https://en.wikipedia.org/wiki/GIO_(software) https://en.wikipedia.org/wiki/GIO_(software)
- slimsag 3y ago"Please don't complain about tangential annoyances—e.g. article or website formats, name collisions, or back-button breakage. They're too common to be interesting." https://news.ycombinator.com/newsguidelines.html https://news.ycombinator.com/newsguidelines.html
- petabyt 3y agoI tried Gio on Android several years ago, and sadly it ran at around 15fps, and the APK was around 50mb I think.
- Nevermark 3y agoThe baseline difference seems to be the difference between organizing GUI elements as stored method+field entities, vs. dynamically combined function+argument entities. It is a lot like the difference between greedy and lazy execution. Which code style is best depends on the structure of the items it is applied to. -- With 100 different views, respectively over 100 different items to be viewed, storing 100 view+item pairs as objects is both general and efficient. With 10 different views, repeatedly over 10 different items to be viewed, there are still 100 interface elements. But repeatedly joining view and item information at draw time provides a 10x space/object savings. And allows for other code simplifications. -- General takeaway: Pre-compiled general libraries, that cannot be treated as inlined compile-time optimizable templates (in the code context where the templates are applied), will be inefficient and overbuilt for cases with more structure and simplicity than they were designed for.
- eru 3y agoWouldn't link-time-optimization take care of your 'general takeaway'?
- Nevermark 3y agoYes, definitely. Link, optimize, compile/code-gen. Instead of optimize, compile, link.
- crq-yml 3y agoI see it as the crossover between approaches amenable to static order and iteration, vs those that demand constraint optimization. This is a recurring problem in programming, because if you code towards the optimal result, you end up making a static, linearized computation that doesn't need further configuration. But if your goal is to provide interfaces and automation, you are tasked with a constraint problem, where you have multiple potential solutions and you either have to filter them down to a single unambiguous result, or find a heuristic that defines the "best one". The problem occurs with type systems, graphical layout, multi-body physics simulation, dependency management and a host of other things. I consider it the most unaddressed subject in CS because it's so relevant to applications and yet industry continually reinvents it in terms of a bespoken algorithm for that one application. And depending on what you're doing, you end up biasing to one or the other method first: a small, well-defined problem only needs the computer to do "brute" things, while a problem dependent on the computer managing the complexity of the problem needs it to find and correct errors.
- the__alchemist 3y agoI've found the immediate-mode UI EGUI in Rust to be easy to use and expressive. It doesn't look native, but the code is easy to read and write for reasons alluded to in the article.
- tverbeure 3y agoHeh, my long weekend project has been to write an egui web application as a crutch for my first steps in Rust. I had no idea that it doesn’t look native.
- refulgentis 3y agoI'm seeing "immediate mode" recently, and I hadn't encountered it before. It is synonymous with a React / Flutter / SwiftUI approach to UI to my untrained eye. Help me fill in the rest?
- flohofwoe 3y agoThe Dear ImGui readme is a good starting point: https://github.com/ocornut/imgui https://github.com/ocornut/imgui ...now of course Dear ImGui is a specific implementation of the immediate mode UI philosophy, but the general ideas transfer to other imguis as well.
- krapp 3y agoThere is also microui, which I like[0], it's much smaller but still gets the job done. Which I forked to work with SDL2[1], no guarantees. It's fun to hack on. [0]https://github.com/rxi/microui https://github.com/rxi/microui [1]https://github.com/kennethrapp/microui https://github.com/kennethrapp/microui
- alpaca128 3y agoImmediate mode means instead of changing the state of UI widgets individually, the entire UI is redrawn with the current state. Afaik this has slightly worse performance but can simplify the code because the UI itself doesn't hold any state.
- flohofwoe 3y ago> because the UI itself doesn't hold any state. ...which isn't actually true in most immediate mode UI frameworks. They absolutely do persist state between frames. That state is just on the other side of the API invisible from the API user. 'Immediate mode UI' is only an API design philosophy, it says nothing about what happens under the hood.
- danpla 3y ago> 'Immediate mode UI' is only an API design philosophy, it says nothing about what happens under the hood. Well, if you have a traditional immediate mode API like: if (button("Start")) start(); Then it's not just about the API philosophy: at the very least, it ties the event handling to the drawing.
- jheriko 3y agoi tire of IM vs retained discussions. the difference is academic up-to tools and code-gen in my experience. you can make one with the other up-to a point of usability. the classic point of split i find is if a UI designer wants to insert intermediate "for-show" elements, e.g. for animation. in that space imgui is, in practice, just going to disable your ui designers vs a retained mode solution using well established tools for defining and animating ui in standard ways. sure you can undo that problem, but thats code work, code work that blocks your ui people from doing their job until its done, and more points of failure for bugs to creep in... the arguments i hear about debuggability seem brain-dead, but on reflection that might be the utility here. "make things easier to debug, shittier programmers can do work"... and that is not to be taken lightly or dismissively when it has real world weight. retained mode most often exists in the backend, e.g. Win32, although some of it may use IM style interfaces, e.g. MessageBox, and so a lot of im gui tools will still use something retained under the hood, and have to go to some lengths to be able to identify "dynamically created" things. yes it can be worked around, but its another headache and bug vector... ive honestly never seen IM GUI as a great approach, most often i implement it due to demand, and with some frustration at the brain dead arguments levelled for it. it solves a problem of programmer burden, which is not that useful in real world projects in my experience, and since the interfaces are interchangeable, its not really a fundamental decision to be making either until someone else forces it. EDIT: to be clear, imagine trying to debug your data-defined if-statement. really think it through and implement it.
- SeanAnderson 3y agoI cannot recommend immediate mode GUI programming based on the limitations I've experienced working with egui (https://github.com/emilk/egui https://github.com/emilk/egui) in Rust. egui does not support putting two widgets in the center of the screen: https://github.com/emilk/egui/issues/3211 https://github.com/emilk/egui/issues/3211 It's really easy to get started with immediate mode and bust out some simple UIs, but the second you start trying to involve dynamically sized elements and responsive layouts -- abandon all hope. The fact it has to calculate everything in a single pass makes these things hard/impossible. Coming from a strong CSS/React background I find the limitation maddening. ... that said, I'm still using it to build a prototype UI for https://ant.care/ https://ant.care/ (https://github.com/MeoMix/symbiants https://github.com/MeoMix/symbiants) because it's the best thing I've found so far. I'm crossing my fingers that Bevy's UI story (or Kayak https://github.com/StarArawn/kayak_ui https://github.com/StarArawn/kayak_ui) becomes significantly more fleshed out sooner rather than later. Bevy 0.13 should have lots more in this area though (https://github.com/bevyengine/bevy/discussions/9538 https://github.com/bevyengine/bevy/discussions/9538)
- kevingadd 3y agoIt's best used for developer tools or simple UIs that don't have complex layout constraints. For what it's worth, I'm building all of my game's UI using a pseudo-imgui framework, but I've had to do manual layout in specific places, and I updated the layout engine to run a second pass in specific cases (dynamically sized elements, primarily when text is being auto-wrapped to fit available space). This sort of stuff is only possible when you control things end-to-end. In practice even these IMGUI frameworks don't generally do their layout in "one pass", it just appears to be a single pass to you. oui and its derivative layout.h both do a size calculation pass and then an arranging pass, for example. I originally used layout.h's algorithm, but eventually designed a new one which operates in ~3 passes: * 1. Calculate minimum sizes and, for containers with multiple rows/columns, construct 'runs' of sequential boxes in a given row/column. * 2a. For containers with wrapping enabled, scan over runs and when we find one that's too big for its container's available space, split controls from one run into a new one. * 2b. For containers with children, scan through their children and grow any children that are meant to expand into available space. (You can't do this until you've measured everything and wrapped.) * 2c. For any containers where you wrapped controls or expanded controls, recalculate their size and throw out the result from 1, since wrapping/expanding potentially changes their size. * 2d. For simplicity you can introduce an alternative version of pass 2 for 'grid layout', where children all have fixed sizes and predictable wrapping. I've only started doing this recently, but it's great for things like listboxes and dataviews. If you do this, you don't need to do the multiple subpasses of 2a/2b/2c, and arranging becomes easier. * 3. Now that you've measured everything and distributed boxes into rows/columns, you can scan through each 'run' and put every control into its place, applying things like centering and RTL/LTR modes. I do think "it should be possible to efficiently perform layout for your whole UI from scratch every frame" is a good principle, it pressures you to architect your application in a cleaner, less fragile way. But sometimes you really want to retain stuff, like shaped glyphs for big blocks of unicode text, etc. Right now my game runs over 120FPS on a terrible laptop from 2015 and around 800FPS on my 3-year-old workstation, but a major portion of the CPU time is all spent doing layout. That's not great.
- tuckerpo 3y agoCasey Muratori of handmade hero fame is one of the original pioneers (potentially the first?) of immediate mode user-interfaces. Check out this lecture/demo from nearly 20 years ago: https://www.youtube.com/watch?v=Z1qyvQsjK5Y https://www.youtube.com/watch?v=Z1qyvQsjK5Y
- nxobject 3y agoFor what it's worth, early user interface libraries existed on a spectrum from what we'd now call retained-mode to immediate-mode. For example, the original Macintosh Toolbox (1984) worked _somewhat_ like that: on one hand, you had to handle events – even to the extent that you were just given a mouse click event, and had to dispatch it to the menu, scrollbars, title bars, etc; you then had to manually draw controls (but not while explicitly passing in their state.) On the other hand, control state was "retained", to the extent that you updated their values, displayed them etc. with handles, and their state existed off in a linked list somewhere. Here's how a later version of Inside Macintosh described having to handle a scroll bar operation, once a click and its location was identified. (I present it because it's long and aggravating...) 1. Use the FindControl, GetControlValue, and TrackControl functions to help calculate the scrolling distance. 2. If you are scrolling for any reason other than the user dragging the scroll box, use the SetControlValue procedure to move the scroll box a corresponding amount. 3. Use a routine—such as the QuickDraw procedure ScrollRect or the TextEdit procedure TEPinScroll—to move the bits displayed in the window by the calculated scrolling distance. Then either use a call that generates an update event or else directly call your application’s DoUpdate routine, which should perform the rest of these steps. 4. Use the UpdateControls procedure to update the scroll bars and then call the Window Manager procedure DrawGrowIcon to redraw the size box. 5. Use the QuickDraw procedure SetOrigin to change the window origin by an amount equal to the scroll bar settings so that the upper-left corner of the document lies at (0,0) in the window’s local coordinate system. (You perform this step so that your application’s document-drawing routines can draw in the correct area of the window.) 6. Call your application’s routines for redrawing the document inside the window. 7. Use the SetOrigin procedure to reset the window origin to (0,0) so that future Window Manager and Control Manager routines draw in the correct area of the window. 8. Return to your event loop. These steps are explained in greater detail in the rest of this section.
- abhibeckert 3y ago> the program is in control of the main event loop, user input is handled as part of program flow Is that supposed to be a good thing? I don't want to write an event loop - I'll probably screw it up and introduce bugs. > the program state is both minimal [...] Um... The comparison of normal web programming and your proposed alternative shows an order of magnitude more code for the same result. And it's not even really the same result, I can't select text and right click to copy for example. What about complex things like varying the UX depending on the size of the screen and input method. Or accessibility features for someone who's blind or can't move their hands... those aren't optional. > and cleanly separated. Huh? You've got a function called "loop()" that contains all of the code. Where is the separation?
- parentheses 3y agoimmediate mode is a tool for certain jobs. drawing arbitrary stuff on screen without layouts or structure would be where I bring it in.
- bschwindHN 3y agoPlease don't ship immediate mode GUIs to normal users. They are good for adding UI to a game or throwing together some quick internal tool, but you'll quickly run into tons of limitations, inconsistent behavior for the platform, and difficult styling. > creating user interfaces for mobile and the desktop, avoiding the platform bound and often complex native toolkits Especially for mobile, just use the native toolkit, or something that uses the native toolkit for its backend. I'm sick of using apps that don't use the native toolkit, they almost always have worse performance and just behave in weird ways. Even flutter is guilty of this, and that has all the manpower of a google team behind it. A mobile app using immediate mode, written in _Go_, just sounds like a recipe for an app that will never function as well as its equivalent written specifically for the platform. Stop sacrificing the experience of your users for your own personal developer experience.
- deleted 3y ago[deleted]
- flohofwoe 3y agoThe RemedyBG debugger (https://remedybg.handmade.network/ https://remedybg.handmade.network/) and the Tracy profiler (https://github.com/wolfpld/tracy https://github.com/wolfpld/tracy) both use Dear ImGui and so far I've only read high praise from people who used those tools compared to the 'established' alternatives. For tools like this, programmers are also just "normal users", and from the developer side, I'm sure they evaluated various alternatives with all their pros and cons before settling for Dear ImGui.
- danpla 3y agoI didn't use RemedyBG or Tracy, but I did try ImHex (https://github.com/WerWolv/ImHex https://github.com/WerWolv/ImHex) and it loaded 12% of the CPU because everything is being repainted 60 times per second. Heck, it even has an option to limit the FPS, which solves the CPU load a bit, but at the same time results in sluggish input because the event handling is tied to the drawing frequency. So yes, the experience was not good, and I don't see what these tools would lose by using a proper GUI. I don't want every utility to drain my laptop battery like a decent video game. ImGui is great if you already have a loop where everything is unconditionally redrawn every frame, but otherwise it's a really odd choice for an end-user application.
- c-smile 3y agoEach tool is good for particular tasks it was designed for. That's why my Sciter [1] supports both - as retained mode (DOM/CSS) as immediate mode (element.paintXXX()). Consider the task of marking some div as resizable - with eight square handles [2]. With immediate mode drawing that task is trivial: const div = ...; // draw sizing handles: div.paintForeground = function(gfx) { gfx.fillColor = "#0f0"; for(let r of this.sizingHandlePlaces()) gfx.fillRect(r); } otherwise, if we have only retained mode as in browsers, we will need to modify the DOM heavily and create temporary elements for handles. [1] https://sciter.com https://sciter.com [2] https://stackoverflow.com/questions/20984181/how-do-i-make-a-usercontrol-sizable-on-runtime-with-sizing-handles https://stackoverflow.com/questions/20984181/how-do-i-make-a...
- dang 3y agoRecent and related: Dear ImGui: Graphical User Interface library for C++ - https://news.ycombinator.com/item?id=38710818 https://news.ycombinator.com/item?id=38710818 - Dec 2023 (109 comments)
- theanonymousone 3y agoIs Streamlit an immediate mode UI framework? It has a very unique, easy-to-start, model for creating UIs which avoids callbacks, but I don't know what the technical term for it is.
- kragen 3y agoyeah, i would call streamlit an imgui framework. also react