我正试图从头开始为一个项目(也是为了学习目的)编写一个GUI库,它运行得很好,但由于这是我的第一次尝试,我觉得事件系统的设计没有那么好。
基本上,我现在处理事件的方式是,每当发生鼠标单击时,我会遍历所有的小部件(例如,按钮),并测试鼠标坐标是否驻留在其中一个小部件中,如果是,我调用事件回调(一个函数指针),它存储在按钮类本身中!
所以我在想另一个(更好的?)设计:
相反,我想要的是一个事件队列,每当事件发生时(例如,单击一个按钮),我就会做与以前相同的事情(即找出单击了哪个按钮),然后构造该事件的一个对象(即ButtonClickedEvent),然后将其添加到队列中,并在稍后呈现框架之后处理它。
这就是我被弄糊涂的地方。
我应该如何在不造成混乱的情况下构建整件事情?换句话说,有没有一种标准的做法?
我一直在寻找有关这方面的一些信息,但我发现的只是如何在现有的库中处理事件(比如java、QT、...etc)。
因此,如果在座的任何人都能解释它的工作原理,那将是非常感谢的!
发布于 2019-11-26 13:36:48
对于这个答案,我将假设小部件不是,也不能是操作系统窗口。
开胃菜:键盘输入。
这个想法是,一些小部件有键盘焦点。您可以跟踪它是什么小部件(如果您有用于小部件的方法来表示它们支持键盘输入,则不会将键盘焦点分配给不支持的小部件)。然后,在注册事件时,使用键盘将事件发送到小部件。
主菜:指向输入(鼠标,触摸或类似)。
是的,您可以遍历所有内容并检查边界。那可不太好。
最好使用空间分区。也就是说,您将创建一个树结构,其中每个节点代表视图端口/窗口的一个区域。根目录是完整的工作区,叶子与小部件的are匹配。现在您可以在树中导航,以找出单击了什么。
可以更快地做到这一点:创建一个位图/纹理,其中每个像素/纹理的颜色都是映射到小部件的id。然后,你只需根据需要阅读它们。我似乎记得有些浏览器会这么做,但我不确定。
无论您选择什么结构,都不要忘记在小部件移动时更新它。
配菜:事件队列。
是也不是。我的意思是,您可能已经有来自操作系统的消息队列了。通常的解决办法是依靠这一点。
请注意,您可能对在队列中放置某些内容感兴趣(以便其他线程可以使用它们放置与UI交互的代码,以便UI线程处理它)。如果为此使用操作系统队列是不可行的(例如,由于任何原因,您希望每个窗口多个),则创建自己的。
饮料:盛事冒泡。
小部件可以将事件标记为已处理或未处理。如果未处理该事件,则将事件发送到容器小部件,依此类推。那就是你把这件事搞砸了。
但是,如果要处理预览事件,则按相反的顺序传播它们。例如,这对于允许容器拦截密钥很有用。
甜点:渲染。
您将如何允许小部件自行绘制?记住,我在这里假设它们不是操作系统窗口。您可以给他们一个API,允许他们做图形原语。或者,您可以为他们提供一个图形缓冲区/位图/纹理,让他们任意使用它。而且,是的,你需要知道窗口的是什么,你要运行一个回调,让他们执行他们的代码。您可能还希望进行双缓冲和垂直同步。然而,这超出了这个问题的范围。
https://softwareengineering.stackexchange.com/questions/401661
复制相似问题