GUI 在低级别检测正在单击哪个元素的常见方法是什么?

What are common ways that GUIs detect which element is being clicked, in a low level?

提问人:PiFace 提问时间:5/1/2021 更新时间:5/1/2021 访问量:674

问:

我一直在尝试四处寻找这个问题,但我发现的都与一个高级问题有关,比如“如何知道正在点击哪个 HTML”。这不是我要找的那种东西。我正在寻找一个更低级的细节。

假设有人试图为给定系统编写 GUI 库。另外,假设该程序员已经设法在屏幕上显示图形、文本、按钮等。现在,他们希望实现用户与该界面交互的方式,更具体地说,使用鼠标点击(或触摸输入)。

运行其 GUI 引擎的系统能够告诉他们何时发生点击,以及点击发生在屏幕上的哪个 (x, y) 点。要查找屏幕上的哪些元素正在被点击,一个简单的方法是遍历每个元素并测试每个元素。但是,在现有 GUI 中通常是这样完成的吗?例如,这是浏览器在显示 HTML 页面时所做的吗?这是操作系统对其 GUI 和窗口的处理方式吗?他们是否使用更复杂的数据结构,如 R-Trees?他们如何处理移动元素?

这个问题并不特定于任何软件,我只是想知道在 GUI 开发的上下文中通常如何解决这个问题。

算法 用户界面 数据结构 语言无关

评论


答:

5赞 Spektre 5/1/2021 #1

有 2 种基本方法。一个你已经想通了:

  1. 测试“每个”对象与鼠标位置

    这可以通过使用空间细分结构(类似于 2D 中的 BVH 和 octree)来加快速度。但是,这种方法总是较慢,并且受制于复杂性,例如 GUI 元素的数量或位置。这里有一个幼稚的例子:O(log(n))O(n)nO(n)

    但是,一旦被测项目数量增加或形状过于复杂,这种方法就很麻烦。

  2. 使用索引缓冲区

    这种方法在复杂性方面是像素完美的,并且在大多数实现中也几乎是免费的。O(1)

    这个想法是具有与被测元素的屏幕保持 ID(索引)相同的分辨率的索引缓冲区,而不是颜色。因此,在渲染 GUI 时,除了使用颜色设置元素的每个像素外,还可以在索引缓冲区中的相同位置设置渲染项索引或 ID。

    在此之后,检测只是在鼠标位置获取索引缓冲区值。这里有几个例子:

    此方法也可用于 2D 和投影 3D->2D 甚至更高尺寸。

评论

0赞 PiFace 5/4/2021
因此,为了澄清:假设我有一个 200x100 的矩形按钮,位于 1600x900 屏幕上的位置 (700,400)。此索引缓冲区的大小为 1600*900=1440000,我应该将其间隔内的索引设置为按钮 ID。这是对的吗?(x,y) | 700 <= x <= 900, 400 <= y <= 500
0赞 Spektre 5/4/2021
@PiFace如果按钮是矩形的,那么是的......如果它是圆角矩形或不同的形状,那么你只为那些属于按钮的x,y设置ID(除非你只对BBOX选择感到满意,否则矩形也可以)。通常将实际渲染合并到 rgb 和索引在一起(例如在 OpenGL 中使用颜色附件等......这使得实现这种方法变得非常简单)如果 GUI 元素不改变形状或位置,那么这可以在任何窗口调整大小事件中只做一次,然后从那时起使用它......
0赞 Spektre 5/4/2021
@PiFace 如果遇到内存问题,可以使用低 n 倍的分辨率作为索引缓冲区(导致选择不准确)..您知道索引缓冲区中的一个像素覆盖了 2x2 , 3x3 , ...RGB 中的像素
0赞 PiFace 5/5/2021
您是否有任何参考资料/材料可以进一步阅读此主题?我想更多地了解它,以便实际实现它。AFAIK,我目前使用的工具不允许我像您展示的示例那样直接访问缓冲区,所以我将尝试其他替代方案。但是,尽管使用了语言或库,但您的回答对于了解可能的方法非常有帮助!也许有一天我会尝试学习 OpenGL
0赞 Spektre 5/5/2021
@PiFace 不,我没有任何关于此的教程或文档......这很简单,就像实现深度缓冲区一样,除了代码和这个简单的描述之外,没有太多其他要添加的。你使用什么 gfx api/lib?很难相信您无法访问像素......你显然可以渲染,所以制作索引缓冲区只是渲染图像的问题。在一些库中,可以使用其他选项,例如 Depth、Stencil、Shadow......缓冲区。。。或渲染到纹理,渲染到位图,...或渲染到屏幕但不显示,存储结果,然后重新渲染正常的 RGB 输出。