openglwidget.h
// openglwidget.h
#ifndef OPENGLWIDGET_H
#define OPENGLWIDGET_H
#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <QVector2D>
#include <QColor>
class OpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core
{
Q_OBJECT
public:
explicit OpenGLWidget(QWidget *parent = nullptr);
~OpenGLWidget();
void drawLine(const QVector2D &start, const QVector2D &end, const QColor &color = Qt::red);
void clear();
protected:
void initializeGL() override;
void resizeGL(int w, int h) override;
void paintGL() override;
private:
GLuint VAO, VBO;
QVector<QVector2D> vertices;
QColor lineColor;
bool hasLine;
};
#endif // OPENGLWIDGET_H
openglwidget.cpp
// openglwidget.cpp
#include "openglwidget.h"
#include <QOpenGLShaderProgram>
OpenGLWidget::OpenGLWidget(QWidget *parent)
: QOpenGLWidget(parent), hasLine(false)
{
QSurfaceFormat format;
format.setVersion(3, 3);
format.setProfile(QSurfaceFormat::CoreProfile);
setFormat(format);
}
OpenGLWidget::~OpenGLWidget()
{
makeCurrent();
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
doneCurrent();
}
void OpenGLWidget::initializeGL()
{
initializeOpenGLFunctions();
glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
// 创建和编译着色器程序
QOpenGLShaderProgram shaderProgram;
shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex,
"#version 330 core\n"
"layout (location = 0) in vec2 aPos;\n"
"void main() {\n"
" gl_Position = vec4(aPos, 0.0, 1.0);\n"
"}");
shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment,
"#version 330 core\n"
"out vec4 FragColor;\n"
"uniform vec4 lineColor;\n"
"void main() {\n"
" FragColor = lineColor;\n"
"}");
shaderProgram.link();
// 设置顶点数据和缓冲
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// 启用抗锯齿
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void OpenGLWidget::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
}
void OpenGLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
if (hasLine && vertices.size() >= 2)
{
QOpenGLShaderProgram shaderProgram;
shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex,
"#version 330 core\n"
"layout (location = 0) in vec2 aPos;\n"
"void main() {\n"
" gl_Position = vec4(aPos, 0.0, 1.0);\n"
"}");
shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment,
"#version 330 core\n"
"out vec4 FragColor;\n"
"uniform vec4 lineColor;\n"
"void main() {\n"
" FragColor = lineColor;\n"
"}");
shaderProgram.link();
shaderProgram.bind();
shaderProgram.setUniformValue("lineColor", lineColor);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(QVector2D), vertices.constData(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(VAO);
glLineWidth(2.0f);
glDrawArrays(GL_LINES, 0, vertices.size());
glBindVertexArray(0);
}
}
void OpenGLWidget::drawLine(const QVector2D &start, const QVector2D &end, const QColor &color)
{
makeCurrent();
vertices.clear();
vertices << start << end;
lineColor = color;
hasLine = true;
update();
doneCurrent();
}
void OpenGLWidget::clear()
{
makeCurrent();
vertices.clear();
hasLine = false;
update();
doneCurrent();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "openglwidget.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
class OpenGLWidget *glWidget;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "openglwidget.h"
#include <QVBoxLayout> // 必须包含这个头文件
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 手动创建OpenGL Widget并添加到containerWidget中
glWidget = new OpenGLWidget(ui->containerWidget);
QVBoxLayout *layout = new QVBoxLayout(ui->containerWidget);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(glWidget);
ui->containerWidget->setLayout(layout);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
// 定义线的起点和终点(标准化设备坐标)
QVector2D start(-0.8f, -0.5f); // 左下方
QVector2D end(0.8f, 0.5f); // 右上方
// 绘制蓝色直线
glWidget->drawLine(start, end, QColor(0, 150, 255));
}