opengl 简单滑动条类实现

说明:

          出于学习目的,自己写了一个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;//r
				pixels[index * 4 + 1] = 0;//g
				pixels[index * 4 + 2] = 0;//b
				pixels[index * 4 + 3] = 0;//a
			}
		}
		for (int i = 0; i < length; i++)//横向
		{
			index = 0.5*slidheight*length + i;

			pixels[index * 4 + 0] = 255;//r
			pixels[index * 4 + 1] = 0;//r
			pixels[index * 4 + 2] = 0;//b
			pixels[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];//滑动条左下角x
		int y0 = pos0[1] - slidheight / 2;//左下角y
		int x1 = pos0[0] + length;//右上角x
		int y1 = pos0[1] + slidheight/2;//右上角y

		if ((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,所以还需要减半个高才是左下角的y
		glDrawPixels(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;
}


你可能感兴趣的:(UI,Class,OpenGL)