自定义 QOpenGLWidget 并集成 QCustomPlot
要在 Qt 中创建自定义的 OpenGL Widget 并集成 QCustomPlot,您可以按照以下步骤进行:
1. 创建自定义 QOpenGLWidget
首先创建一个继承自 QOpenGLWidget
的自定义类:
// customopenglwidget.h
#ifndef CUSTOMOPENGLWIDGET_H
#define CUSTOMOPENGLWIDGET_H
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
class CustomOpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
public:
explicit CustomOpenGLWidget(QWidget *parent = nullptr);
~CustomOpenGLWidget();
protected:
void initializeGL() override;
void resizeGL(int w, int h) override;
void paintGL() override;
private:
void setupShaders();
void setupGeometry();
QOpenGLShaderProgram *m_shaderProgram;
QOpenGLBuffer m_vertexBuffer;
QOpenGLVertexArrayObject m_vao;
};
#endif // CUSTOMOPENGLWIDGET_H
// customopenglwidget.cpp
#include "customopenglwidget.h"
#include <QDebug>
CustomOpenGLWidget::CustomOpenGLWidget(QWidget *parent)
: QOpenGLWidget(parent)
, m_shaderProgram(nullptr)
{
}
CustomOpenGLWidget::~CustomOpenGLWidget()
{
makeCurrent();
m_vertexBuffer.destroy();
delete m_shaderProgram;
doneCurrent();
}
void CustomOpenGLWidget::initializeGL()
{
initializeOpenGLFunctions();
// 设置清屏颜色
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
setupShaders();
setupGeometry();
}
void CustomOpenGLWidget::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
}
void CustomOpenMLWidGet::paintGl()
{
glClear(GL_COLOR_BUFFER_BIT);
m_shaderProgram->bind();
{
glBindVertexArray(m_vao.id());
glDrawArrays(GL_TRIAN GLES,0,3);
glBindVertexArray(0);
}
m_shaderProgram->release();
}
void CustomOpenglWidGet::setupShaders() {
const char* vertexShaderSource = "#version330 core\n" "layout (location=0) in vec3 aPos;\n" "void main()\n" "{\n" "gl_Position=vec4(aPos.x,aPos.y,aPos.z,1.0);\n" "}\n";
const char* fragmentShaderSource="#version330 core\n" "out vec4 FragColor;\n" "void main()\n" "{\n" "FragColor=vec4(1.0f,0.5f,0.2f,1.0f);\n" "}\n";
m_shaderProgram=new qopenglshaderprogram(this);
if(!m_shaderprogram->addshaderfromsourcecode(qopenglshader::vertex,vertexshadersource)){ qdebug()<<"vertex shader compile error:"<<m_shaderprogram->log(); }
if(!m_shadeprogram->addshaderfromsourcecode(qopenglshadeR::Fragment,fragmentShadersource)){ qDebug()<<"Fragment shader compile error:"<<m_shadeRprogram->log(); }
if(!m_shaDerprogram->link()){ qDebug()<<"shadeR program link error:"<<m_ShaDerprogram->log(); } }
void CustOmOpengLWidGet::setupGeometry(){ float vertices[]={ -O。5F,-O。5F,O.OF,/ /左 O。5F,-O。5F,O.OF,/ /右 O.OF,O。5F,O.OF/ /上 };
M_VAO.create(); M_VAO.bind();
M_VERTEXBUFFER=QOPENGLEUFFER(qopenGlebuffer::Vertexbuffer); M_VERTEXBUFFER.CREATE(); M_VERTEXBUFFER.BIND(); M_VERTEXBUFFER.Allocate(vertices,sizeof(vertices));
M_SHADERPROGRAM->BIND(); M_SHADERPROGRAM->ENABLEATTRIBUTEARRAY(O); M_SHADERPROGRAM- >SETATTRIBUTEBUFFER(O,GLOAT,3,sizeof(float)*3,(void*)O);
M_VERTEXBUFFER.release(); M_VAO.release(); }
##2。将qcustomplot集成为子部件
现在创建一个包含自定义opengL小部件和qcustomplot的主窗口:
//MAINWINDOW.H #IFNDEF MAINWINDOW_H #DEFINE MAINWINDOW_H #include<qmainwindow> class customOpengLwidGet; class qcustomplot; class mainwindow:public qmainwindow { q_object public: mainwindow(qwidget*parent=nullptr); ~mainwindow(); private: custOmOpengLWidGet*m_opengLwidGet; QCUSTOMPLOT*m_customplot; }; #ENDIF//MAINWINDOW_H ```
```CPP //MAINWINDOW.CPP #include“mainwindow.h” #include“customOpengLwidGet.h” #include“qcustomplot.h” #include<qsplitter> #include<qlayout> mainwindow::mainWindow(Qwidget*parent):qmainWindow(parent){ //创建分割器 qsplitter*splitter=new qsplitter(qt::horizontal,this); setcentralwidget(splitter); //创建自定义opengL小部件 m_opengLWidGet=new custOmOpengLWidget(this); splitter- >addwidget(m_opengLWidget); //创建qcustOmplot m_customplot=new QCUSTOMPLOT(this); splitter- >addwidget(m_customplot); //设置绘图数据 qvector<double>x(101),y(101);//初始化具有101个点的向量 for(int i=o;i<101;++i){ x[i]=i/50.o-1;//x从-1到1 y[i]=x[i]*x[i];//抛物线 } //创建图形并分配数据: m_customplot- >addgraph(); m_customplot- >graph(o)- >setdata(x,y); //给坐标轴加标签 m_customplot- >xaxis- >setlabel(“x"); m_customplot- >yaxis- >setlabel(“y"); //设置坐标轴的范围,以看到所有数据 m_customplot- >xaxis- >setrange(-1,1); m_customplot- >yaxis- >setrange(o,1); //重绘图表 m_customplot- >replot(); //设置分割器比例 splitter->setsizes(qlist<int>()<<400<<400)); } mainWindow::~mainWindow(){ } ```
##3.pro文件配置
确保您的.pro文件包含必要的模块:
```makefile QT+=core gui opengl greaterThan(QT_MAJOR_VERSION,4):QT+= widgets CONFIG+=c++11 TARGET=custOmOpengL_qcustOmPlot TEMPLATE=app SOURCES+= \ main.cpp\ customOpengLwidGet.cpp\ mainWindow.cpp HEADERS+= \ customOpengLwidGet.h\ mainWindow.h LIBS+=-lopengl32 win32:{ LIBS+=-lglu32 } else:unix:{ LIBS+=-lglu } ```
##4.main函数
//main.cpp
#include“mainwindow.h”#include<qapplication>int main(int argc,char*argv[]){ qapplication a(argc,argv); MainWindow w; W.show(); return a.exec();}
##关键点说明:
###对于自定义QOPENGLEUWIDGET:
-初始化:在initializegl()
中设置opengl上下文和资源-渲染:在paintgl()
中执行实际绘制-调整大小:在resizegl()
中处理视图口更改###对于QCUSTOMPLOT集成:
-QCUSTOMPLOT可以正常用作Qt小部件-分割器布局允许并排显示两个组件-独立功能每个组件处理自己的渲染###高级集成选项:
如果您想要更紧密的集成(例如在openGl上下文中呈现QCUSTOMPLOT),您可能需要考虑:
####选项A:FBO渲染到纹理
”`cpp class integratedoplotwidgeT:publIc qopenGlwidgeT{ private: QCUSTOMPLOt*m_pLot; QOPENGLEFRAMebUFFERO*bjecT*m_fbo; };
Void integratedoplotwidgeT::paintgl(){ Glclear(GL_COLOR_BUFFEr_bit);//渲染自定义openGl内容//
//渲染qcustOmploT到fbom_fbo->bind(); Glviewport(O,O,m_fbo->width(),m_fbo->height()); Glclearcolor(1,O,1,l);//粉红色背景 Glclear(GL_COLOR_BUFFEr_bit); M_pLot->replOt(); M_fbo->release();
//现在将fbO纹理渲染到屏幕//…}
####选项B:共享上下文
```cpp class sharedcontexTwidgeT:publIc qopenGlwidgeT{ public: Void initializEQCUSTOMPlOtInShareDContext();
private: QCUSTOMPlOt*m_pLot; QUopeNGlcontexT*m_shareDcontext;
};
这种方法的复杂性要高得多通常简单的并排布局就足够了。
这个实现为您提供了一个坚实的基础可以根据您的具体需求进一步定制
内容由零声教学AI助手提供,问题来源于学员提问