GUI 在低级别检测正在单击哪个元素的常见方法是什么?
What are common ways that GUIs detect which element is being clicked, in a low level?
我一直在努力寻找这个问题,但我发现的都是与高层次的事情有关,比如“如何知道哪个 HTML 被点击了”。那不是我要找的东西。我正在寻找更底层的细节。
假设有人正在尝试为给定系统编写 GUI 库。另外,假设这个程序员已经设法在屏幕上显示图形、文本、按钮等。现在他们想要实现用户与该界面交互的方式,更具体地说,使用鼠标点击(或者可能是触摸输入)。
他们运行 GUI 引擎的系统能够告诉他们点击何时发生,以及点击发生在屏幕上的哪个 (x, y) 点。要找到屏幕上的哪些元素被点击,一种简单的方法是循环遍历每个元素并测试它们中的每一个。但这是现有 GUI 中通常的做法吗?例如,这是浏览器在显示 HTML 页面时所做的吗?这是操作系统对其 GUI 和 windows 所做的吗?他们是否使用更复杂的数据结构,如 R-Trees?他们如何处理移动元素?
这个问题并不特定于任何软件,我只是想知道在 GUI 开发的上下文中通常如何解决这个问题。
有两种基本方法。一个你已经想通了:
测试“每个”对象与鼠标位置
可以通过使用空间细分结构(类似于 2D 中的 BVH 和八叉树)来加快速度。然而,这种方法总是比较慢,并且会受到复杂性的限制,例如 O(log(n))
或 O(n)
,其中 n
是 GUI 元素的数量。这里是天真的 O(n)
示例:
- simple C++ Drag&Drop example
但是一旦测试的物品数量增多或者形状过于复杂,这种方法就很麻烦了。
使用索引缓冲区
这种方法是像素完美的,但复杂度 O(1)
,并且在大多数实现中也几乎是免费的。
我们的想法是让索引缓冲区的分辨率与屏幕的分辨率相同,保存测试元素的 ID(索引)而不是颜色。因此,当您渲染 GUI 时,除了为元素的每个像素设置颜色之外,您还在索引缓冲区中的相同位置设置渲染项目索引或 ID。
此后检测只是获取鼠标位置的索引缓冲区值。这里有几个例子:
- VCL/GDI index buffer based mouse select
此方法也可用于 2D 和投影 3D->2D 或更高维度。
我一直在努力寻找这个问题,但我发现的都是与高层次的事情有关,比如“如何知道哪个 HTML 被点击了”。那不是我要找的东西。我正在寻找更底层的细节。
假设有人正在尝试为给定系统编写 GUI 库。另外,假设这个程序员已经设法在屏幕上显示图形、文本、按钮等。现在他们想要实现用户与该界面交互的方式,更具体地说,使用鼠标点击(或者可能是触摸输入)。
他们运行 GUI 引擎的系统能够告诉他们点击何时发生,以及点击发生在屏幕上的哪个 (x, y) 点。要找到屏幕上的哪些元素被点击,一种简单的方法是循环遍历每个元素并测试它们中的每一个。但这是现有 GUI 中通常的做法吗?例如,这是浏览器在显示 HTML 页面时所做的吗?这是操作系统对其 GUI 和 windows 所做的吗?他们是否使用更复杂的数据结构,如 R-Trees?他们如何处理移动元素?
这个问题并不特定于任何软件,我只是想知道在 GUI 开发的上下文中通常如何解决这个问题。
有两种基本方法。一个你已经想通了:
测试“每个”对象与鼠标位置
可以通过使用空间细分结构(类似于 2D 中的 BVH 和八叉树)来加快速度。然而,这种方法总是比较慢,并且会受到复杂性的限制,例如
O(log(n))
或O(n)
,其中n
是 GUI 元素的数量。这里是天真的O(n)
示例:- simple C++ Drag&Drop example
但是一旦测试的物品数量增多或者形状过于复杂,这种方法就很麻烦了。
使用索引缓冲区
这种方法是像素完美的,但复杂度
O(1)
,并且在大多数实现中也几乎是免费的。我们的想法是让索引缓冲区的分辨率与屏幕的分辨率相同,保存测试元素的 ID(索引)而不是颜色。因此,当您渲染 GUI 时,除了为元素的每个像素设置颜色之外,您还在索引缓冲区中的相同位置设置渲染项目索引或 ID。
此后检测只是获取鼠标位置的索引缓冲区值。这里有几个例子:
- VCL/GDI index buffer based mouse select
此方法也可用于 2D 和投影 3D->2D 或更高维度。