所谓辉煌的人生,不过是欲望的囚徒。
——叔本华
注:自本节开始,所有的示例都以 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 fps
fpsTimer = 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 fps
fpsTimer = 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 w, int h);