GLUI 子窗口模板






3.67/5 (12投票s)
本文详细介绍了如何设置一个 OpenGL 窗口,并将控件布局和组织到 GLUI 子窗口中,并为你的 OpenGL 应用程序提供一个模板。
目录
引言
本文向您展示了如何为您的 OpenGL 应用程序创建 GUI 控件,并将它们组织到 GLUI
子窗口中。在本文中,我们将使用上一篇文章 GLUI 窗口模板 的源代码,并对其进行修改,以便我们的 GLUI
控件将布局在两个子窗口中,而不是一个窗口中。
本文可以按以下方式使用
- 了解如何使用
GLUI
子窗口 - 理解 OpenGL 中的视口概念
- 将程序用作需要 GUI 控件的 OpenGL 应用程序的模板
如果您不知道什么是 OpenGL、GLUT
、GLUI
,请先查看 GLUT 窗口模板 文章。
为什么要有一个 GLUI 子窗口模板?
将一个单独的窗口来容纳我们的 GLUI
控件有时会让用户感到烦恼,因为用户每次想要执行某个操作时,都需要将焦点从 OpenGL 上下文窗口移开。避免这种情况的一个好方法是将 GLUI
控件直接放置在 GLUT
OpenGL 窗口中,将它们嵌入到 GLUI
子窗口中。
为了避免每次想要创建一个带有 GLUI
子窗口中控件的 OpenGL 图形应用程序时都要编写相同的代码,这个程序代码可以用作模板,让您直接开始。
OpenGL GLUI
子窗口模板具有以下属性
- 窗口标题:“
GLUI
子窗口模板” - 两个包含
GLUI
控件的GLUI
子窗口- 第一个子窗口将包含一些控件,并放置在窗口的左侧。它将被称为垂直
GLUI
子窗口,因为控件将在其中垂直布局 - 第二个子窗口将包含剩余的控件,并放置在窗口的底部。它将被称为水平子窗口,因为控件将在其中水平布局
- 第一个子窗口将包含一些控件,并放置在窗口的左侧。它将被称为垂直
GLUI
窗口,我们的图形将在其中绘制,并且我们的两个GLUI
子窗口将放置在其中- 处理我们
GLUT
窗口和GLUI
控件的事件 - 通过命令行提示符显示事件何时何地发生及其含义
用法
编译与运行程序
有关如何编译和运行程序的详细信息,请查看 GLUI 窗口模板 文章中的 用法 部分。
Using the Code
源代码旨在用作您的 OpenGL 应用程序的模板。要在新应用程序中使用它,您可以简单地重命名 CPP 文件并将其添加到您的 Visual Studio 项目中。
注意
请注意,GLUI
是一个 C++ 库,因此不能与 C 一起使用。所以,如果您在尝试构建 GLUI
程序时遇到链接错误,只需检查所有文件扩展名是否为 CPP 而不是 C。
代码解释
由于我们在上一篇 GLUI 窗口模板 文章中已经详细介绍了创建带有控件和事件处理的 GLUI
窗口的细节,因此本文我们将关注如何创建子窗口并将控件布局在其中。
1- 创建 GLUI 子窗口
我们将用上一篇文章中的窗口替换为放置在主图形窗口的左侧和底部的两个子窗口。
下图显示了我们在上一篇文章中如何将控件布局到单个 GLUI
窗口中
下图显示了我们将控件布局到放置在我们主 GLUT
窗口的左侧和底部的两个独立子窗口中
GLUI
子窗口的创建如下
// pointer to GLUI two subwindows (horizontal and vertical subwindows)
GLUI *glui_h_subwindow, *glui_v_subwindow;
// Create GLUI horizontal subwindow (placed on bottom)
glui_h_subwindow = GLUI_Master.create_glui_subwindow
(main_window, GLUI_SUBWINDOW_BOTTOM);
// Create GLUI vertical subwindow (placed on left)
glui_v_subwindow = GLUI_Master.create_glui_subwindow
(main_window, GLUI_SUBWINDOW_LEFT);
以下是 create_glui_subwindow
函数的定义,如 GLUI 手册 中所述
GLUI *GLUI_Master_Object::create_glui_subwindow( int window, int position );
Attribute | 描述 |
window |
现有 GLUT 图形窗口的 ID |
位置 |
新子窗口的位置,相对于其嵌入的
您可以在同一相对位置放置任意数量的子窗口;在这种情况下,多个子窗口将简单地堆叠在一起。例如,如果两个子窗口在同一个 |
2- 添加 GUI 控件
幸运的是,向 GLUI
子窗口添加控件与向 GLUI
窗口添加控件完全相同。因此,例如,要将“对象属性”面板添加到 GLUI
垂直子窗口而不是添加到 GLUI
窗口,我们可以简单地更改以下代码片段
从 |
// Add the 'Object Properties' Panel to the GLUI window
GLUI_Panel *op_panel = glui_window->add_panel ("Object Properties");
|
改为 |
// Add the 'Object Properties' Panel to the GLUI vertical subwindow
GLUI_Panel *op_panel = glui_v_subwindow->add_panel ("Object Properties");
|
因此,对于我们所有需要放置在 GLUI
垂直子窗口中的控件,我们可以简单地将 glui_window
替换为 glui_v_subwindow
;对于我们所有想要放置在 GLUI
水平子窗口中的控件,我们需要将 glui_window
替换为 glui_h_subwindow
。
3- 合并 GLUT 和 GLUI
创建我们的两个 GLUI
子窗口后,我们需要让每个子窗口知道其主图形窗口在哪里
// Let the GLUI horizontal subwindow know where its main graphics window is
glui_h_subwindow->set_main_gfx_window( main_window );
// Let the GLUI vertical subwindow know where its main graphics window is
glui_v_subwindow->set_main_gfx_window( main_window );
当 GLUI
子窗口中的控件值发生变化时,会向此主图形窗口发送重绘请求。
4- 处理主窗口的大小调整
当主窗口的大小调整时,我们需要更改视口大小,我们的 OpenGL 图形将在其中绘制。但是,这一次,由于我们在主窗口中添加了 GLUI
子窗口,我们不能简单地将视口宽度和高度设置为等于主窗口的宽度和高度。因此,我们需要考虑以下几点
- 视口 X 位置 = 放置在左侧的
GLUI
子窗口的宽度 - 视口宽度 =
GLUI
窗口宽度 - 放置在左侧的GLUI
子窗口的宽度 - 放置在右侧的GLUI
子窗口的宽度 - 视口 Y 位置 = 放置在顶部的
GLUI
子窗口的高度 - 视口高度 = 主
GLUI
窗口的高度 - 放置在顶部的GLUI
子窗口的高度 - 放置在底部的GLUI
子窗口的高度
值得庆幸的是,GLUI
库通过一种方法为我们提供了自动确定视口绘制区域的 x、y、宽度和高度的功能。这可以通过以下代码片段完成,该代码片段将放置在 reshape 函数中
// Represents the drawing area x, y, width, and height
int vx, vy, vw, vh;
// Get the drawing area viewport characteristics
GLUI_Master.get_viewport_area( &vx, &vy, &vw, &vh );
// Set the viewport
glViewport(vx, vy, vw, vh);
GLUI
库还通过一个函数为我们提供了进一步简化工作的功能。因此,上面的代码片段可以用以下代码替换
GLUI_Master.auto_set_viewport();
以下是 get_viewport_area
和 auto_set_viewport
函数的说明,如 GLUI 手册 中所述
get_viewport_area
确定当前窗口的可绘制区域的位置和尺寸。当使用 GLUI
子窗口时,需要此函数,因为子窗口将占用窗口的一部分区域,而图形应用程序不应覆盖该区域。此函数应在 GLUT
reshape 回调函数中调用。
void GLUI_Master_Object::get_viewport_area(int *x, int *y, int *w, int *h );
Attribute | 描述 |
x 、y 、w 、h |
函数返回时,这些变量将保存当前窗口可绘制区域的 x、y、宽度和高度。然后应将这些值传递给 OpenGL 视口命令 glViewport() 。 |
auto_set_viewport
自动设置当前窗口的视口。此单一函数等效于以下一系列命令
int x, y, w, h;
GLUI_Master.get_viewport_area( &x, &y, &w, &h );
glViewport( x, y, w, h );
函数原型如下,它不接受任何参数
void GLUI_Master_Object::auto_set_viewport( void );
注意
鼠标被动移动和显示事件将不会被记录,以便我们可以清楚地在命令提示符日志中看到其他事件。
结论
本文的目的是教您如何设置一个 GLUT
窗口,其中包含多个带有控件的 GLUI
子窗口,以及事件处理。同时,该模板可用于节省大量从旧项目或互联网复制粘贴的工作。
如果您发现此模板有用或有任何建议,请告诉我。
参考文献
修订历史
- 2007/09/25:发布原始文章