在 WidgetPointView 类中添加如下代码:
class WidgetPointView : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core
{
Q_OBJECT
public:
explicit WidgetPointView(QWidget *parent = nullptr);
protected:
void initializeGL() override;
void resizeGL(int w, int h) override;
void paintGL() override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
private:
QVector<QVector2D> m_points; // 存储所有点的坐标
QVector<QVector2D> m_selectedPoints; // 存储框选中的点的坐标
bool m_selecting = false; // 是否正在进行框选操作
QVector2D m_startPos; // 框选起点
QVector2D m_endPos; // 框选终点
};
WidgetPointView::WidgetPointView(QWidget *parent)
: QOpenGLWidget(parent)
{
}
void WidgetPointView::initializeGL()
{
initializeOpenGLFunctions();
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}
void WidgetPointView::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
}
void WidgetPointView::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(10.0f);
glEnable(GL_POINT_SMOOTH);
glBegin(GL_POINTS);
glColor3f(1.0f, 0.0f, 0.0f);
for (const auto &point : m_points) {
glVertex2f(point.x(), point.y());
}
glEnd();
if (m_selecting) {
glDisable(GL_DEPTH_TEST);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, width(), 0, height());
glColor3f(0.0f, 0.0f, 1.0f);
glLineWidth(1.0f);
glBegin(GL_LINE_LOOP);
glVertex2d(m_startPos.x(), m_startPos.y());
glVertex2d(m_endPos.x(), m_startPos.y());
glVertex2d(m_endPos.x(), m_endPos.y());
glVertex2d(m_startPos.x(), m_endPos.y());
glEnd();
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glEnable(GL_DEPTH_TEST);
}
}
void WidgetPointView::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
m_selecting = true;
m_startPos = QVector2D(event->pos());
m_endPos = QVector2D(event->pos());
}
}
void WidgetPointView::mouseMoveEvent(QMouseEvent *event)
{
if (m_selecting) {
m_endPos = QVector2D(event->pos());
update();
}
}
在 paintGL() 方法中,首先绘制所有点,然后判断是否正在进行框选操作,如果是,就绘制框选的矩形。在 mousePressEvent() 中,如果是鼠标左键按下,就将 m_selecting 设为 true,并记录当前鼠标位置作为框选起点;在 mouseMoveEvent() 中,如果正在框选,就记录当前鼠标位置为框选终点,并调用 update() 方法使窗口重绘。需要注意的是,为了在 2D 坐标系中正确绘制矩形,需要先将当前的变换矩阵保存下来,然后设置投影矩阵为正交投影,绘制完矩形后再恢复变换矩阵和投影矩阵。