(五)OpenGL菜单管理

  1. glutCreateMenu 创建一个弹出式菜单
  2. glutAddMenuEntry 在当前菜单底部增加一个菜单条目
  3. glutAttachMenu 将当前的一个鼠标按键与当前菜单联系起来
  4. glutAddSubMenu 在当前菜单底部增加一个子菜单
  5. glutDetachMenu 释放当前窗口的一个鼠标按键
  6. 获取、设置标识符,删除、更改菜单
      
      在电脑上点击一下鼠标右键,会出现一个菜单。通过本页内容,可以制作出一个这样的菜单(真实网站中不知道用的是什么库)。
      示例结果如下图所示。
    在这里插入图片描述
    本节内容所用示例代码(建议先跳过,本节其它内容看完后再看该代码):
#include<windows.h>
#include <GL/glut.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>

int menu=0,submenu1=0,submenu2;
//画一个绿色多边形
void draw(){
    glClearColor(0,0,0,0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3f(0,1,0);
    glOrtho(-1,1,-1,1,-1,1);
    glBegin(GL_POLYGON);
        glVertex2f(-0.5,-0.5);
        glVertex2f(-0.5,0.5);
        glVertex2f(0.5,0.5);
        glVertex2f(0.5,-0.5);
    glEnd();
    glutSwapBuffers();
}
//点击某个条目时,输出该条目属于哪个菜单
void getcurrentmenu(){
    int nmenu;
    nmenu = glutGetMenu();
    if(nmenu == menu)
        printf("current is main menu.\n");
    else if(nmenu == submenu1)
        printf("current is sub menu 1.\n");
    else if(nmenu == submenu2)
        printf("current is sub menu 2.\n");
}

//第一个子菜单
void submenufunc1(int data){
    getcurrentmenu();
    switch(data){
        case 1:
            printf("sub menu 1's item 1 is triggered.\n");
            break;
        case 2:
            printf("sub menu 1's item 2 is triggered.\n");
            break;
        case 3:
            printf("sub menu 1's item 3 is triggered.\n");
            break;
    }
}
//第二个子菜单
void submenufunc2(int data){
    getcurrentmenu();
    switch(data){
        case 1:
            printf("sub menu 2's item 1 is triggered.\n");
            break;
        case 2:
            printf("sub menu 2's item 2 is triggered.\n");
            break;
        case 3:
            printf("sub menu 2's item 3 is triggered.\n");
            break;
    }
}
//主菜单
void menufunc(int data){
    getcurrentmenu();
    switch(data){
        case 1:
            printf("menu's item 1 is triggered.\n");
            break;
        case 2:
            printf("menu's item 2 is triggered.\n");
            break;
        case 3:
            printf("menu's item 3 is triggered.\n");
            break;
    }
}

int main(int argc,char *argv[]){
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
    glutInitWindowPosition(0,0);
    glutInitWindowSize(512,512);
    glutCreateWindow("test");
    glutDisplayFunc(draw);

    //构建子菜单1的内容
    submenu1 = glutCreateMenu(submenufunc1);
    glutAddMenuEntry("1's item 1",1);
    glutAddMenuEntry("1's item 2",2);
    glutAddMenuEntry("1's item 3",3);
    glutAttachMenu(GLUT_LEFT_BUTTON);
    
    //构建子菜单2的内容
    submenu2 = glutCreateMenu(submenufunc2);
    glutAddMenuEntry("2's item 1",1);
    glutAddMenuEntry("2's item 2",2);
    glutAddMenuEntry("2's item 3",3);
    glutAttachMenu(GLUT_RIGHT_BUTTON);

    //构建主菜单的内容
    menu = glutCreateMenu(menufunc);
    glutAddMenuEntry("item 1",1);
    glutAddMenuEntry("item 2",2);
    glutAddMenuEntry("item 3",3);
    
    //将两个菜单变为另一个菜单的子菜单
    glutAddSubMenu("sub1",submenu1);
    glutAddSubMenu("sub2",submenu2);
    //点击鼠标右键时显示菜单
    glutAttachMenu(GLUT_RIGHT_BUTTON);

    glutMainLoop();
    return 0;
}

名词解释:
菜单:在这里插入图片描述
菜单条目:菜单中的某一选项。
在这里插入图片描述在这里插入图片描述都是菜单条目。

1. glutCreateMenu 创建一个弹出式菜单

int glutCreateMenu( void (* func) (int value) )
参数说明:func 与将要创建的这个菜单相关联的函数。这个函数的作用:点击菜单中的某一选项时,控制系统做出对应的反应。
value 传递给回调函数func的数值,由所选择的菜单条目对应的整型数值确定。
  
  通俗点说,在创建每一个菜单条目时,都会被赋予一个唯一的值。点击某个条目时,该条目对应的值就会被传递给func函数,func函数根据传入的值得知用户点击了哪个条目,然后进行对应的操作。
  下面的代码应该对你理解这个函数会有一点帮助。

void menufunc(int data){
    getcurrentmenu();
    switch(data){
        case 1:
            printf("menu's item 1 is triggered.\n");
            break;
        case 2:
            printf("menu's item 2 is triggered.\n");
            break;
        case 3:
            printf("menu's item 3 is triggered.\n");
            break;
    }
}

int main(){
	menu = glutCreateMenu(menufunc);
	//构建菜单内容
    glutAddMenuEntry("item 1",1);
    glutAddMenuEntry("item 2",2);
    glutAddMenuEntry("item 3",3);
}

2. glutAddMenuEntry 在当前菜单底部增加一个菜单条目

void glutAddMenuEntry(char * name, int value)
参数说明:char *name 菜单条目的内容,比如示例结果图中的item 1和item 2.(这里的name没理解错的话,是地址指针)。
     value,菜单条目的值(索引 )。在一个菜单中,每个条目都有唯一的数值用以区分。
该函数在上面已经有过初次见面了。

	glutAddMenuEntry("item 1",1);
    glutAddMenuEntry("item 2",2);
    glutAddMenuEntry("item 3",3);

3. glutAttachMenu 将当前的一个鼠标按键与当前菜单联系起来

void glutAttachMenu(int button)
  参数说明:button 指明在窗口中按哪种按键会使得菜单出现。可选择的符号常数为:GLUT_LEFT_BUTTON、GLUT_MIDDLE_BUTTON和 GLUT_RIGHT_BUTTON,分别表示鼠标左、中、右键。
  示例代码的最后一行表示单机鼠标右键时会出现菜单。(键盘按键下一节会讲)

4. glutAddSubMenu 在当前菜单底部增加一个子菜单

void glutAddSubMenu(char * name, int menu)
参数说明: name 与glutAddMenuEntry中的name类似,这里是子菜单的名称,比如实际结果图中的 sub1和sub2。
代码示例:

本文开头示例代码的main函数里最后几行。

5. glutDetachMenu 释放当前窗口的一个鼠标按键

void glutDetachMenu(int button)
参数说明:button 与上一个相同
  使用该代码后,会断开鼠标按键和菜单间的联系。点击鼠标按键,对应的菜单将不会再出现(就像游戏里已经被你放生的宠物)。

6. 获取、设置标识符,删除、更改菜单等

6.1 int glutGetMenu(void) 获取当前菜单的标识符
6.2 void glutSetMenu(int menu) 将菜单标识符对应的菜单设置为当前菜单 menu为菜单标识符
6.3 void glutDestroyMenu(int menu) 删除指定菜单 menu为菜单标识符
6.4 void glutChangeToMenuEntry(int entry, char * name, int value)

参数说明:entry 菜单条目的索引,最顶层的为1,向下依次递增。比如示例中item1,item2, item3,sub1,sub2条目的索引分别为1、2、3、4、5.
       name 新的字符串
       value 新的值,也就是glutAddMenuEntry(char *name, int value)中的value
  这里可以理解为改变当前菜单条目的名字。
  比如在示例代码的最后加上一行代码:

 	menu = glutCreateMenu(menufunc);
    glutAddMenuEntry("item 1",1);
    glutAddMenuEntry("item 2",2);
    glutAddMenuEntry("item 3",3);
    glutChangeToMenuEntry(1,"item",1);//增加的代码
    glutAddSubMenu("sub1",submenu1);
    glutAddSubMenu("sub2",submenu2);
    glutAttachMenu(GLUT_RIGHT_BUTTON);

    glutMainLoop();
    return 0;
}

运行结果如下:
在这里插入图片描述
  item1 被改变为 item
  不仅菜单条目可以改变,子菜单条目也可以改变,也就是示例中的sub1和sub2

6.5 void glutChangeToSubMenu(int entry, char *name, int menu)

将当前菜单指定的菜单条目更改为子菜单触发条目
参数说明:entry  与6.4的entry相同,为菜单项的索引
     name,menu  与glutAddSubMenu(char *name, int menu)中的参数对应相同

6.6 void glutRemoveMenuItem(int entry)删除指定的菜单项

entry与6.4的entry相同,为菜单项的索引。

  • 17
    点赞
  • 108
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
OpenGL 是一个用于图形渲染的开放式 API,它可以在不同的平台上被使用。为了增加菜单,可以使用 GUI 框架,如 Qt 或 GLFW。使用命令模式可以实现系统功能扩展,这是因为命令模式将请求封装成一个对象,使得请求的发送者和接收者之间的关系得以解耦,从而可以方便地添加、删除或修改功能。 以下是实现 OpenGL 菜单并利用命令模式扩展系统功能的步骤: 1. 定义菜单项:例如,菜单项可以包括“新建”、“打开”、“保存”等。 2. 创建菜单栏:创建菜单栏可以使用 GUI 框架提供的 API,例如 Qt 中的 QMenuBar 类。 3. 创建命令类:创建命令类可以使用命令模式的模板,例如,每个菜单项对应一个命令类,命令类包含执行命令的方法。 4. 创建命令管理器:命令管理器是一个负责管理所有命令对象的类,它可以将命令对象添加到一个列表中,并提供执行命令的方法。 5. 将菜单项与命令关联:在创建菜单项时,将每个菜单项与对应的命令对象关联,例如,在 Qt 中,可以使用 QAction 类来创建菜单项并关联命令对象。 6. 实现扩展功能:通过创建新的命令类并添加到命令管理器中,可以实现扩展功能。例如,可以创建一个“导出”命令类,并将其添加到命令管理器中,然后将其与一个菜单项关联,从而实现导出功能。 通过使用命令模式实现系统功能扩展,可以实现系统的松耦合和可扩展性,而且可以避免修改现有代码来添加新功能的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值