编程自定义GUI OPenGL



我正在OpenTK中创建自己的GUI。

例如,当光标位于某个GUI控件中时,我想触发鼠标事件。我该怎么做?因为现在我只是在主类中迭代一个项目列表,而在Opentk的窗口的MouseMove事件中,我只是在检查鼠标坐标是否在";区域";我正在绘制的组件。

这目前有效,但我认为可以用更好的方式。这样,我的代码是无序的,并且在主类中,我宁愿将它放在特定的组件类中。

我希望在GUI的每个组件上都附加一个事件,这样我就可以为一个组件定义多个事件。

我的意思是,我希望有一个按钮组件,在那里我可以覆盖或只使用一个在事件发生时触发的方法。与OpenGL的窗口相同,在该窗口中您可以覆盖事件。

这不是一个完整的答案,因为你的问题很宽泛,但我希望它能有所帮助。

为了实现这样的系统,以下是潜在设计的核心组件:

UI组件:某种标准接口,不同的组件类型可以定义交互逻辑。根据语言的不同,最常见的方法可能类似于父类Component,其中包含要重写的方法。这些可能包括以下内容:

  • 鼠标悬停
  • 鼠标点击(按下/释放(
  • 单击并拖动

它可能还需要一些额外的相关信息:

  • 确定组件位置的某种方法。可能是提供一个边界框,或者可能是一个测试给定点是否在此组件内的方法
  • 用于绘制零部件的信息或功能
  • 显示和分层设置(它是可见的还是隐藏的,应该绘制在其他组件的顶部还是后面(

UI上下文:上下文是定义UI中存在的组件集的结构。这可能类似于组件的列表结构。为了构建您的UI,您需要在此上下文中添加组件。上下文将定义一些行为:

  • 管理组件(添加/删除/修改(
  • 如何绘制整个上下文(例如,在每个组件上循环并执行每个组件的绘制功能(
  • 事件处理(见下一节(

事件调度:要使UI可用,您可以插入一个";适配器";处理来自窗口库(OpenTK(的事件的层,然后将它们转换为组件的可用事件并进行分派。这里是一个例子,说明这可能如何对";点击";事件(伪代码(:

function TK_Event_ClickPressed(point) {
for component in context {
if component.ContainsPoint(point) {
component.EventClickPressed()
}
}
}

在我看来,这实际上是设计中更棘手的部分,因为基于组件的UI的工作方式有一些棘手的约定。你不一定要遵循它们,但它们很重要,至少因为这可能是人们期望你的UI工作的方式:

  • 点击-按下后,点击-拖动继续发生,直到点击释放,即使光标离开组件区域
  • "Actions";单击发布时发生
  • 只有在同一组件上发生相应的点击按下时,点击释放才会采取行动
  • 如果光标不再在组件内部,则点击释放不会执行任何操作(不过,在释放之前离开并重新进入组件仍然会执行操作(
  • 一次只能主动单击一个组件(顶部显示的组件(,即使多个组件在该位置重叠

假设您遵循这些约定,这意味着调度事件实际上比检查事件点是否在给定组件中要复杂一些。您需要维护某种状态来跟踪上下文当前是否处于单击状态,以及哪个组件(如果有的话(是";消耗";当前单击。也就是说,如果发生单击-释放和拖动事件,则应向哪个组件提供这些事件。


有了这些系统,您只需要创建一个窗口,创建一个UI上下文,将适配器层注册到窗口中以处理该上下文,设置窗口以在框架上绘制上下文,然后使用上下文添加/删除/修改程序中的组件。

最新更新