opengl 简单滑动条类实现

来源:互联网 发布:怎么查看淘宝信用等级 编辑:程序博客网 时间:2024/05/18 15:03

说明:

          出于学习目的,自己写了一个opengl滑动条的类,虽然简单,但是可以基于这个例子去实现ui部分了.

要实现简单ui的最简单方法也许就是直接在屏幕上操作像素,就是不知道效率怎么样.

关键:

用到了glew中的函数:(我不知道opengl标准库是否有相似的函数,如果有的话宁愿用标准函数.glRasterPos2f我没有搞成功)

              glewWindowspos2d:

函数说明:void glWindowPos2d(GLdouble x,GLdouble  y);

             x:屏幕x坐标;

             y:屏幕y坐标.

            左下角为坐标系原点

作用说明:用于设定滑动条的位置

gl标准函数:

            glDrawPixels:

            函数说明:

            glDrawPixels (GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);

            width,height:图像的宽和高;

            format:像素缓存的类型:比如GL_RGBA,GL_RGB,与pixels分配缓存是w*h*(4或者3)对应,很重要;

            type为数据类型;

            pixels:像素缓存

作用说明:

            将像素数据拷贝到帧缓存中.

SlidBar类:

说明:

显示结果:


黄色竖条为可移动的部分.

坐标系:

            左下角为坐标原点.

            这个类有两种使用方法.

class SlidBar{private:GLdouble pos0[2];//滑动条在屏幕上的位置GLdouble pos_point[2];//滑动点的位置GLint length;//滑动条长度,单位:像素GLfloat ratio;//0-1,滑动条当前百分比unsigned char* pixels;//滑动条的像素信息GLdouble highvalue;//滑动条达到100%时的数值GLdouble lowvalue;//0%时的数值void SetRatio(int x)//设置百分比,滑动点{ratio = (GLfloat)GLfloat(x - pos0[0]) / GLfloat(length);pos_point[0] = pos0[0] + length*ratio;printf("ratio %f\n",ratio);}void SetPixels()//改变像素信息,也就是滑动条的ui图像{unsigned int index;for (int i = 0; i < slidheight; i++)//初始化,全部设置成透明状态{for (int j = 0; j < length; j++){index = i*length + j;//像素矩阵第i行第j列,每个"单位"有rgba四个值需要设置pixels[index * 4 + 0] = 0;//rpixels[index * 4 + 1] = 0;//gpixels[index * 4 + 2] = 0;//bpixels[index * 4 + 3] = 0;//a}}for (int i = 0; i < length; i++)//横向{index = 0.5*slidheight*length + i;pixels[index * 4 + 0] = 255;//rpixels[index * 4 + 1] = 0;//rpixels[index * 4 + 2] = 0;//bpixels[index * 4 + 3] = 255;//a}for (int j = 0; j < slidheight; j++)//纵向{index = j*length;//最左边的边界,表现为一条红色的竖"1"pixels[index * 4 + 0] = 255;pixels[index * 4 + 1] = 0;pixels[index * 4 + 2] = 0;pixels[index * 4 + 3] = 255;index = j*length + length - 1;//最右边的边界,同上pixels[index * 4 + 0] = 255;pixels[index * 4 + 1] = 0;pixels[index * 4 + 2] = 0;pixels[index * 4 + 3] = 255;index = j*length + (length - 1)*ratio;//当前滑动点的位置,表现为一条黄色的竖"1"pixels[index * 4 + 0] = 255;pixels[index * 4 + 1] = 255;pixels[index * 4 + 2] = 0;pixels[index * 4 + 3] = 255;}}public:SlidBar(){}~SlidBar(){free(pixels);}void Init(GLdouble* pos0, GLfloat ratio, GLint length)//策略1:只返回ratio{this->pos0[0] = pos0[0];//滑动条位置this->pos0[1] = pos0[1];this->ratio = ratio;//初始百分比this->length = length;//长度pos_point[0] = pos0[0] + length*ratio;//滑动点的位置pos_point[1] = pos0[1];this->pixels = new unsigned char[length *slidheight * 4];//初始化像素缓存SetPixels();//根据当前状态在像素缓存中进行绘制}void Init_value(GLdouble* pos0, GLfloat ratio, GLint length,GLdouble lowvalue,GLdouble highvalue)//策略2:直接获得最低值和最高值,返回现在的值{this->pos0[0] = pos0[0];this->pos0[1] = pos0[1];this->ratio = ratio;this->length = length;pos_point[0] = pos0[0] + length*ratio;pos_point[1] = pos0[1];this->pixels = new unsigned char[length *slidheight * 4];SetPixels();this->lowvalue = lowvalue;this->highvalue = highvalue;}GLfloat GetRatio()//获得当前百分比{return ratio;}GLdouble GetValue()//如果使用策略2,用这个函数获得当前值{return (lowvalue + (highvalue - lowvalue)*ratio);}bool TouchTest(int x, int y)//由传进来的鼠标坐标(左下角为原点,所以可能需要变换)测试是否点中{bool target = false;int x0 = pos0[0];//滑动条左下角xint y0 = pos0[1] - slidheight / 2;//左下角yint x1 = pos0[0] + length;//右上角xint y1 = pos0[1] + slidheight/2;//右上角yif ((x>x0) && (x<x1) && (y>y0) && (y<y1))//是否在上面这个矩形中{target = true;SetRatio(x);//设置百分比SetPixels();//改变像素信息,重新画图}return target;}void DrawSlid()//根据像素信息显示{__glewWindowPos2d(pos0[0], pos0[1]-slidheight/2);//在屏幕相应的位置放置滑动条,pos0[1]-slidheight/2:pos0[1]其实是滑动条半高处的y,所以还需要减半个高才是左下角的yglDrawPixels(length, slidheight, GL_RGBA, GL_UNSIGNED_BYTE, this->pixels);}};

使用方法:

两种策略:

            1.只使用滑动条的百分比,具体数值需要通过百分比自己在外部计算

            声明:slidBar test0;

            初始化:

            GLdouble pos[2] = { 20, 40 };//在屏幕中的位置.屏幕坐标原点设定为左下角
            test0.Init(pos, rat, 200);//这里的rat是初始状态滑动条的百分比,200代表滑动条是200像素长度

2.直接在slidbar中设置需要控制的数值的上下范围,并通过slidbar返回当前滑动条所在位置的值.

            这两种策略在上面这个类中都有实现.

            声明:slidBar test0;

            初始化:

            GLdouble pos[2] = { 20, 40 };//在屏幕中的位置.屏幕坐标原点设定为左下角
            GLfloat rat = colors[0] / 1;//colors[0]为测试用的变量,需要用slidbar调整的某个变量
            test0.Init_value(pos, rat, 200,0,1);


一个测试例子:
要求:
            画一个矩形,滑动条改变矩形颜色的r通道.范围(0-1)
完整代码:
#include <GL/glew.h>#include <gl/glut.h>#include <stdio.h>#pragma comment(lib,"glew32.lib")int width = 600;int height = 600;int  slidheight = 20;GLfloat colors[4] = { 1, 1, 1, 1 };class SlidBar{这里是上面贴出来的SlidBar类代码,直接拷贝代替};SlidBar test1;void myDisplay(void){glClearColor(0.0, 0.0, 0.0, 1.0);glClear(GL_COLOR_BUFFER_BIT);glColor4fv(colors);glBegin(GL_TRIANGLES);glVertex2f(-0.6, -0.5);glVertex2f(0.6, -0.5);glVertex2f(0, 0.4);glEnd();test1.DrawSlid();glFlush();}void uiinit(){GLdouble pos[2] = { 20, 40 };GLfloat rat = colors[0] / 1;//test1.Init(pos, rat, 200);test1.Init_value(pos, rat, 200,0,1);}void init(){uiinit();}void mouse(int button, int state, int x, int y){if (state == GLUT_DOWN&&button == GLUT_LEFT_BUTTON){printf("x:%d,y:%d\n", x, y);if (test1.TouchTest(x, height - y)){//GLfloat rat = test1.GetRatio();//colors[0] = 1 * rat;colors[0] = test1.GetValue();}}glutPostRedisplay();}int main(int argc, char *argv[]){glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);glutInitWindowPosition(100, 100);glutInitWindowSize(width, height);glutCreateWindow("test");glEnable(GL_BLEND);//启用这个特性,放置ui背景覆盖实际画面glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);init();glewInit();glutDisplayFunc(&myDisplay);glutMouseFunc(mouse);glutMainLoop();return 0;}


1 0