最近因为项目原因,涉及显示图像,其实只是单纯的划线,但是线条的数量很庞大,所以需要用到opengl来提升性能,一些基础功能也是琢磨的3天左右,基本上是出来了。
下面直接看代码:
初始化:
用qopenglwidget这三个函数必须有
void GLWidget::initializeGL()
{
initializeOpenGLFunctions(); //这个是qt使用opengl方法接口
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
f->glClearColor(1.0f, 1.0f, 1.0f, 1.0f); //设置窗体背景色
int w = this->width();
int h = this->height();
glOrtho(0.0,w,h,0.0,-1.0,1.0); //这个代表截取屏幕,这里我这里截取整个屏幕
}
第一次运行程序的时候,会设置一次窗体大小,执行
void GLWidget::resizeGL(int w, int h)
{
glViewport(0, 0, w, h); //这里是显示窗体,上面有截取,这里才有显示。不然窗口不会显示任何内容
}
接下来就是绘制图像了:
void GLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glColor3f(0.0, 0.0,0.0);
for(int i=0;i<m_SatrtXList.size();i++) //这里我是画了100万条线。速度大概1秒左右
{
glLineWidth(1);
glBegin(GL_LINES); //画线
glVertex2d(m_SatrtXList[i],m_SatrtYList[i]); //开始点(x,y)
glVertex2d(m_EndXList[i],m_EndYList[i]); //结束点 (x,y)
glEnd();
}
}
注意,qopenwidget所有的绘制只能在paintGL中进行,所有的操作只能传值进入paintGL进行绘制。
平移:
平移和qt的无边框窗口移动很像。
void GLWidget::mousePressEvent(QMouseEvent *event)
{
if(event->button()==Qt::LeftButton)
{
m_bClicked=true;
pLast = event->globalPos() - this->pos(); //点击之后获取当前位置(记录当前点)
}
}
松开鼠标,这个没什么好说的。
void GLWidget::mouseReleaseEvent(QMouseEvent *event)
{
m_bClicked=false;
}
重点来了。
在鼠标移动的时候,一直获取当前位置
void GLWidget::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() && Qt::LeftButton&&m_bClicked)
{
m_MovePoint=event->globalPos();
qDebug()<<"m_MovePoint::"<<m_MovePoint<<"pLast::"<<pLast;
glFlush(); //刷新界面 理论上应该这个就会执行paintGL,但是不行,还需要update一下
update();
}
}
在paintGL中增加以下代码:
这样我们就实现了平移。
接下来我们需要实现局部缩放。
如果只是需要淡出的缩放,那么直接使用opengl的函数 glScalef(scalex,scaley,scalez); 2d开发的话scalez为0;
但是我们还需要局部进行放大,其实局部放大无非就是在放大之前进行平移坐标到鼠标位置,但是如何移动到精准位置,需要使用一定比例进行缩放。
void GLWidget::wheelEvent(QWheelEvent *event)
{
m_Point= event->globalPos(); //获取当前位置,注意所有的坐标都是相对于桌面的坐标
m_Fzoom=1; //设置默认缩放比例 opengl有一个毛病,就是他认为只有比初始值大为放大
//比初始值小为缩小,所以每次都设置一次初值
m_bWheel=true;
qDebug()<<"point:"<<m_Point;
if(event->delta() > 0) {
m_Fzoom += 0.1; //滚轮 向上
} else {
m_Fzoom -= 0.1;
}
glFlush();
update();
}
在paintGL中加入以下代码
if(m_bWheel)
{
//进行平移,如果不需要局部则把平移部分去掉。
glTranslatef(m_Point.x()*(1-m_Fzoom),m_Point.y()*(1-m_Fzoom),0);
glScalef(m_Fzoom, m_Fzoom, 0.0);
}
m_Fzoom=1;
m_bWheel=false;
这样的话局部缩放也完成了,那么我们来看下效果图。