https://github.com/emilk/egui#why-immediate-mode
为什么立即模式
egui
是立即模式 GUI 库,与保留模式GUI 库相对。保留模式和立即模式之间的区别最好用按钮的例子来说明:在保留的 GUI 中,您创建一个按钮,将其添加到某些 UI 并安装一些单击处理程序(回调)。该按钮保留在 UI 中,要更改其上的文本,您需要存储对它的某种引用。相比之下,在即时模式下,您可以立即显示按钮并与之交互,并且您每帧都这样做(例如每秒 60 次)。这意味着不需要任何点击处理程序,也不需要存储对它的任何引用。在egui
这看起来像这样:if ui.button("Save file").clicked() { save(file); }
。
可以在egui
文档中找到对立即模式的更详细描述。
两种系统都有优点和缺点。
简而言之:即时模式 GUI 库更易于使用,但功能较弱。
立即模式的优点
可用性
立即模式的主要优点是应用程序代码变得非常简单:
- 您永远不需要任何中断代码流的点击处理程序和回调。
- 您不必担心挥之不去的回调调用已经消失的东西。
- 您的 GUI 代码可以轻松地存在于一个简单的函数中(不需要仅用于 UI 的对象)。
- 您不必担心应用程序状态和 GUI 状态不同步(即 GUI 显示过时的内容),因为 GUI 不存储任何状态 - 它立即显示最新状态。
换句话说,大量代码、复杂性和错误都消失了,您可以将时间集中在比编写 GUI 代码更有趣的事情上。
立即模式的缺点
布局
立即模式的主要缺点是它使布局更加困难。假设您想在屏幕中央显示一个小对话窗口。要正确定位窗口,GUI 库必须首先知道它的大小。要知道窗口的大小,GUI 库必须首先对窗口的内容进行布局。在保留模式下,这很容易:GUI 库进行窗口布局,定位窗口,然后检查交互(“是否单击了 OK 按钮?”)。
在即时模式下,您会遇到一个悖论:要知道窗口的大小,我们必须进行布局,但布局代码还会检查交互(“是否单击了 OK 按钮?”),因此它需要知道窗口位置在显示窗口内容之前。这意味着我们必须在知道窗口大小之前决定在哪里显示窗口!
这是立即模式 GUI 的一个基本缺点,任何解决它的尝试都有其自身的缺点。
一种解决方法是存储大小并在下一帧使用它。这会为正确的布局产生帧延迟,偶尔会在出现的第一帧出现闪烁。egui
这样做是为了某些事情,例如窗口和网格布局。
您也可以调用布局代码两次(一次获取尺寸,一次进行交互),但这不仅成本更高,而且实现起来也很复杂,在某些情况下两次是不够的。egui
从不这样做。
对于“原子”小部件(例如按钮)egui
在显示之前就知道大小,因此可以在egui
没有任何特殊解决方法的情况下将按钮、标签等居中。
CPU使用率
由于即时模式 GUI 对每一帧进行完整布局,因此布局代码需要快速。如果您有一个非常复杂的 GUI,这可能会对 CPU 造成负担。特别是,在滚动区域中拥有非常大的 UI(具有非常长的回滚)可能会很慢,因为内容需要在每一帧中进行布局。
如果您在设计 GUI 时考虑到这一点并避免使用巨大的滚动区域(或只布置可见的部分),那么性能损失通常很小。对于大多数情况,您可以期望egui
每帧占用 1-2 毫秒,但egui
仍有很大的优化空间(这不是我关注的重点)。您还可以设置egui
仅在有交互(例如鼠标移动)时重绘。
如果您的 GUI 是高度交互的,那么与保留模式相比,立即模式实际上可能具有更高的性能。转到任何网页并调整浏览器窗口的大小,您会注意到浏览器进行布局的速度非常慢,并且会占用大量 CPU。egui
相比之下,调整窗口大小,您将获得流畅的 60 FPS,而无需额外的 CPU 成本。
身份证
您希望 GUI 库保留一些 GUI 状态,即使是在即时模式库中,例如egui
. 这包括窗口的位置和大小以及用户在某些 UI 中滚动的距离。在这些情况下,您需要提供egui
唯一标识符的种子(在父 UI 中是唯一的)。例如:默认情况下egui
使用窗口标题作为唯一 ID 来存储窗口位置。如果您想要两个具有相同名称的窗口(或一个具有动态名称的窗口),您必须提供一些其他 ID 源egui
(一些唯一的整数或字符串)。
egui
还需要跟踪正在与哪个小部件进行交互(例如,正在拖动哪个滑块)。egui
为此使用唯一的 id:s,但在这种情况下,ID 是自动生成的,因此用户无需担心。特别是,有两个同名的按钮是没有问题的(这与 形成对比Dear ImGui
)。
总的来说,ID 处理是一个罕见的不便,并不是一个很大的缺点。
标签:窗口,egui,布局,模式,立即,按钮,GUI From: https://www.cnblogs.com/itfanr/p/16963776.html