所谓辉煌的人生,不过是欲望的囚徒。
——叔本华
注:自本节开始,所有的示例都以 OpenGLWidget 实现,
一、鼠标事件
重写鼠标事件,
#ifndef MYOPENGL_H
#define MYOPENGL_H#include <QOpenGLWidget>
#include <QTimer>
#include <QMouseEvent>class MyOpenGL : public QOpenGLWidget
{
public:MyOpenGL(QWidget *parent = nullptr);
public slots:void onTimerUpdate();
protected:void initializeGL();void resizeGL(int w, int h);void paintGL();void mousePressEvent(QMouseEvent *event); // 鼠标点击事件void mouseMoveEvent(QMouseEvent *event); // 鼠标移动事件void mouseReleaseEvent(QMouseEvent *event); // 鼠标释放事件
private:QTimer * fpsTimer = nullptr;bool isPressed = false;
};#endif // MYOPENGL_H
#include "live2d/LAppDelegate.hpp"
#include "live2d/LAppView.hpp"
#include "live2d/LAppPal.hpp"
#include "live2d/LAppLive2DManager.hpp"
#include "live2d/LAppDefine.hpp"#include "myopengl.h"MyOpenGL::MyOpenGL(QWidget *parent):QOpenGLWidget{parent} {// 60 fpsfpsTimer = new QTimer(this);fpsTimer->start((1.0/60.0)*1000);connect(fpsTimer,&QTimer::timeout,this,&MyOpenGL::onTimerUpdate);
}void MyOpenGL::onTimerUpdate()
{update();
}void MyOpenGL::initializeGL(){LAppDelegate::GetInstance()->Initialize(this);
}void MyOpenGL::resizeGL(int w, int h){LAppDelegate::GetInstance()->resize(w,h);
}void MyOpenGL::paintGL(){LAppDelegate::GetInstance()->update();
}void MyOpenGL::mouseMoveEvent(QMouseEvent*e){LAppDelegate::GetInstance()->GetView()->OnTouchesMoved(e->x(),e->y());update();e->ignore();
}void MyOpenGL::mousePressEvent(QMouseEvent*e){if(e->button() == Qt::LeftButton){isPressed = true;LAppDelegate::GetInstance()->GetView()->OnTouchesBegan(e->x(),e->y());}e->ignore();
}
void MyOpenGL::mouseReleaseEvent(QMouseEvent*e){if(e->button() == Qt::LeftButton){isPressed = false;LAppDelegate::GetInstance()->GetView()->OnTouchesEnded(e->x(), e->y());update();}e->ignore();
}
效果如下,
二、实时追踪
窗口默认设置为不追踪鼠标移动,只有鼠标按键按下时才影响鼠标移动 mousePressEvent 事件,我们可以通过 setMouseTracking 方法调整为实时追踪,
setMouseTracking(true);
// ...MyOpenGL::MyOpenGL(QWidget *parent):QOpenGLWidget{parent} {// 60 fpsfpsTimer = new QTimer(this);fpsTimer->start((1.0/60.0)*1000);connect(fpsTimer,&QTimer::timeout,this,&MyOpenGL::onTimerUpdate);setMouseTracking(true);
}// ...
效果如下,
三、全屏追踪
全屏追踪的方案有两种:
- 窗口全屏(应用级)。重写 QT 的鼠标事件,是仅针对于当前窗口的鼠标捕获,一旦脱离了当前窗口,就没法捕获系统的鼠标事件。
- 使用系统钩子(系统级)。这种方法涉及到操作系统级别的编程,需要特殊权限和对应平台的 API 知识。
除了实现全屏追踪,我们还需要鼠标穿透到桌面来操作其他窗口,而应用级的鼠标穿透 Qt::WA_TransparentForMouseEvents 不会再接收系统级的鼠标事件。综合考虑,我们采用方案 2 实现全屏追踪。
1、鼠标钩子
#ifndef MYOPENGL_H
#define MYOPENGL_H#include <QOpenGLWidget>
#include <QTimer>
#include <QMouseEvent>
#include <Windows.h>
#include <QWindow>class MyOpenGL : public QOpenGLWidget
{
public:MyOpenGL(QWidget *parent = nullptr);static MyOpenGL* GetInstance();~MyOpenGL();void mouseMoveCallBack(float x,float y);void mouseReleaseCallBack(float x,float y);void mousePressCallBack(float x,float y);
public slots:void onTimerUpdate();
protected:void initFpsTimer();void initializeGL();void resizeGL(int