360免费建站域名,admin管理员登录,进口网站建设,外贸建站用什么服务器OpenGL笔记之事件驱动设计将相机控制类和应用程序类分离 —— 2024-10-02 下午 bilibili赵新政老师的教程看后笔记
code review! 文章目录 OpenGL笔记之事件驱动设计将相机控制类和应用程序类分离1.代码图片2.分析3.UML4.代码 1.代码图片 运行
Mouse button 1 pressed at (1…OpenGL笔记之事件驱动设计将相机控制类和应用程序类分离 —— 2024-10-02 下午 bilibili赵新政老师的教程看后笔记
code review! 文章目录 OpenGL笔记之事件驱动设计将相机控制类和应用程序类分离1.代码图片2.分析3.UML4.代码 1.代码图片 运行
Mouse button 1 pressed at (100, 200)
Mouse dragged by (50, 50)
Key pressed: 65
Updating camera control2.分析
类图: #mermaid-svg-QbSNpe6eTiluDCBI {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-QbSNpe6eTiluDCBI .error-icon{fill:#552222;}#mermaid-svg-QbSNpe6eTiluDCBI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-QbSNpe6eTiluDCBI .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-QbSNpe6eTiluDCBI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-QbSNpe6eTiluDCBI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-QbSNpe6eTiluDCBI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-QbSNpe6eTiluDCBI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-QbSNpe6eTiluDCBI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-QbSNpe6eTiluDCBI .marker.cross{stroke:#333333;}#mermaid-svg-QbSNpe6eTiluDCBI svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-QbSNpe6eTiluDCBI g.classGroup text{fill:#9370DB;fill:#131300;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-QbSNpe6eTiluDCBI g.classGroup text .title{font-weight:bolder;}#mermaid-svg-QbSNpe6eTiluDCBI .nodeLabel,#mermaid-svg-QbSNpe6eTiluDCBI .edgeLabel{color:#131300;}#mermaid-svg-QbSNpe6eTiluDCBI .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-QbSNpe6eTiluDCBI .label text{fill:#131300;}#mermaid-svg-QbSNpe6eTiluDCBI .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-QbSNpe6eTiluDCBI .classTitle{font-weight:bolder;}#mermaid-svg-QbSNpe6eTiluDCBI .node rect,#mermaid-svg-QbSNpe6eTiluDCBI .node circle,#mermaid-svg-QbSNpe6eTiluDCBI .node ellipse,#mermaid-svg-QbSNpe6eTiluDCBI .node polygon,#mermaid-svg-QbSNpe6eTiluDCBI .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-QbSNpe6eTiluDCBI .divider{stroke:#9370DB;stroke:1;}#mermaid-svg-QbSNpe6eTiluDCBI g.clickable{cursor:pointer;}#mermaid-svg-QbSNpe6eTiluDCBI g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-QbSNpe6eTiluDCBI g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-QbSNpe6eTiluDCBI .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-QbSNpe6eTiluDCBI .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-QbSNpe6eTiluDCBI .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-QbSNpe6eTiluDCBI .dashed-line{stroke-dasharray:3;}#mermaid-svg-QbSNpe6eTiluDCBI #compositionStart,#mermaid-svg-QbSNpe6eTiluDCBI .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-QbSNpe6eTiluDCBI #compositionEnd,#mermaid-svg-QbSNpe6eTiluDCBI .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-QbSNpe6eTiluDCBI #dependencyStart,#mermaid-svg-QbSNpe6eTiluDCBI .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-QbSNpe6eTiluDCBI #dependencyStart,#mermaid-svg-QbSNpe6eTiluDCBI .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-QbSNpe6eTiluDCBI #extensionStart,#mermaid-svg-QbSNpe6eTiluDCBI .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-QbSNpe6eTiluDCBI #extensionEnd,#mermaid-svg-QbSNpe6eTiluDCBI .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-QbSNpe6eTiluDCBI #aggregationStart,#mermaid-svg-QbSNpe6eTiluDCBI .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-QbSNpe6eTiluDCBI #aggregationEnd,#mermaid-svg-QbSNpe6eTiluDCBI .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-QbSNpe6eTiluDCBI .edgeTerminals{font-size:11px;}#mermaid-svg-QbSNpe6eTiluDCBI :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Application -cameraControl: CameraControl* -mouseCallback: MouseCallback -keyCallback: KeyCallback Application() setMouseCallback(MouseCallback) setKeyCallback(KeyCallback) triggerMouseEvent(MouseEvent) triggerKeyEvent(KeyEvent) run() «interface» CameraControl handleMouseEvent(MouseEvent) handleKeyEvent(KeyEvent) update() SimpleCameraControl -mousePressed: bool -lastX: double -lastY: double -keys: map handleMouseEvent(MouseEvent) handleKeyEvent(KeyEvent) update() MouseEvent x: int y: int button: int pressed: bool KeyEvent key: int 上面的类图展示了代码中主要类的结构和关系:
Application 类包含一个 CameraControl 指针和事件回调函数指针,通过 setMouseCallback 和 setKeyCallback 设置事件回调。CameraControl 是一个抽象基类,定义了处理鼠标事件、键盘事件和更新的接口。SimpleCameraControl 继承自 CameraControl,实现了具体的事件处理逻辑。MouseEvent 和 KeyEvent 分别表示鼠标事件和键盘事件的数据结构。
事件处理流程图: #mermaid-svg-eIrf11OOE2jJgv7u {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-eIrf11OOE2jJgv7u .error-icon{fill:#552222;}#mermaid-svg-eIrf11OOE2jJgv7u .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-eIrf11OOE2jJgv7u .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-eIrf11OOE2jJgv7u .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-eIrf11OOE2jJgv7u .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-eIrf11OOE2jJgv7u .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-eIrf11OOE2jJgv7u .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-eIrf11OOE2jJgv7u .marker{fill:#333333;stroke:#333333;}#mermaid-svg-eIrf11OOE2jJgv7u .marker.cross{stroke:#333333;}#mermaid-svg-eIrf11OOE2jJgv7u svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-eIrf11OOE2jJgv7u .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-eIrf11OOE2jJgv7u .cluster-label text{fill:#333;}#mermaid-svg-eIrf11OOE2jJgv7u .cluster-label span{color:#333;}#mermaid-svg-eIrf11OOE2jJgv7u .label text,#mermaid-svg-eIrf11OOE2jJgv7u span{fill:#333;color:#333;}#mermaid-svg-eIrf11OOE2jJgv7u .node rect,#mermaid-svg-eIrf11OOE2jJgv7u .node circle,#mermaid-svg-eIrf11OOE2jJgv7u .node ellipse,#mermaid-svg-eIrf11OOE2jJgv7u .node polygon,#mermaid-svg-eIrf11OOE2jJgv7u .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-eIrf11OOE2jJgv7u .node .label{text-align:center;}#mermaid-svg-eIrf11OOE2jJgv7u .node.clickable{cursor:pointer;}#mermaid-svg-eIrf11OOE2jJgv7u .arrowheadPath{fill:#333333;}#mermaid-svg-eIrf11OOE2jJgv7u .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-eIrf11OOE2jJgv7u .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-eIrf11OOE2jJgv7u .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-eIrf11OOE2jJgv7u .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-eIrf11OOE2jJgv7u .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-eIrf11OOE2jJgv7u .cluster text{fill:#333;}#mermaid-svg-eIrf11OOE2jJgv7u .cluster span{color:#333;}#mermaid-svg-eIrf11OOE2jJgv7u div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-eIrf11OOE2jJgv7u :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} mouseCallback keyCallback 鼠标/键盘事件 Application::triggerMouseEvent/triggerKeyEvent onMouseEvent onKeyEvent SimpleCameraControl::handleMouseEvent SimpleCameraControl::handleKeyEvent 事件处理流程如下:
应用程序触发鼠标或键盘事件事件通过 Application::triggerMouseEvent 或 Application::triggerKeyEvent 分发到对应的全局回调函数回调函数 onMouseEvent 或 onKeyEvent 调用 SimpleCameraControl 的对应事件处理函数SimpleCameraControl 的事件处理函数根据事件数据进行相应的处理
主程序流程图: #mermaid-svg-hAJgD3cOIhvTAfMh {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-hAJgD3cOIhvTAfMh .error-icon{fill:#552222;}#mermaid-svg-hAJgD3cOIhvTAfMh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hAJgD3cOIhvTAfMh .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-hAJgD3cOIhvTAfMh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hAJgD3cOIhvTAfMh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hAJgD3cOIhvTAfMh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hAJgD3cOIhvTAfMh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hAJgD3cOIhvTAfMh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hAJgD3cOIhvTAfMh .marker.cross{stroke:#333333;}#mermaid-svg-hAJgD3cOIhvTAfMh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hAJgD3cOIhvTAfMh .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-hAJgD3cOIhvTAfMh .cluster-label text{fill:#333;}#mermaid-svg-hAJgD3cOIhvTAfMh .cluster-label span{color:#333;}#mermaid-svg-hAJgD3cOIhvTAfMh .label text,#mermaid-svg-hAJgD3cOIhvTAfMh span{fill:#333;color:#333;}#mermaid-svg-hAJgD3cOIhvTAfMh .node rect,#mermaid-svg-hAJgD3cOIhvTAfMh .node circle,#mermaid-svg-hAJgD3cOIhvTAfMh .node ellipse,#mermaid-svg-hAJgD3cOIhvTAfMh .node polygon,#mermaid-svg-hAJgD3cOIhvTAfMh .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hAJgD3cOIhvTAfMh .node .label{text-align:center;}#mermaid-svg-hAJgD3cOIhvTAfMh .node.clickable{cursor:pointer;}#mermaid-svg-hAJgD3cOIhvTAfMh .arrowheadPath{fill:#333333;}#mermaid-svg-hAJgD3cOIhvTAfMh .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hAJgD3cOIhvTAfMh .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hAJgD3cOIhvTAfMh .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-hAJgD3cOIhvTAfMh .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-hAJgD3cOIhvTAfMh .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hAJgD3cOIhvTAfMh .cluster text{fill:#333;}#mermaid-svg-hAJgD3cOIhvTAfMh .cluster span{color:#333;}#mermaid-svg-hAJgD3cOIhvTAfMh div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hAJgD3cOIhvTAfMh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} main 创建Application对象 设置鼠标回调为onMouseEvent 设置键盘回调为onKeyEvent 调用Application::run 模拟触发鼠标事件 模拟触发键盘事件 调用CameraControl::update 主程序的流程如下:
创建 Application 对象设置鼠标回调函数为 onMouseEvent设置键盘回调函数为 onKeyEvent调用 Application::run 模拟触发鼠标事件模拟触发键盘事件调用 CameraControl::update 更新相机状态
3.UML
------------------
| CameraControl | abstract
------------------
| handleMouseEvent(MouseEvent) : void |
| handleKeyEvent(KeyEvent) : void |
| update() : void |
------------------^||
----------------------
| SimpleCameraControl |
----------------------
| -mousePressed : bool |
| -lastX : double |
| -lastY : double |
| -keys : mapint, bool |
----------------------
| handleMouseEvent(MouseEvent) : void |
| handleKeyEvent(KeyEvent) : void |
| update() : void |
-----------------------------------------
| Application |
-------------------
| -cameraControl : SimpleCameraControl*
| -mouseCallback : MouseCallback |
| -keyCallback : KeyCallback |
-------------------
| setMouseCallback(MouseCallback) : void |
| setKeyCallback(KeyCallback) : void |
| triggerMouseEvent(MouseEvent) : void |
| triggerKeyEvent(KeyEvent) : void |
| run() : void |
--------------------------------------
| MouseEvent |
-------------------
| x : int |
| y : int |
| button : int |
| pressed : bool |
------------------------------------
| KeyEvent |
-----------------
| key : int |
-------------------------------------
| Global Functions |
--------------------
| onMouseEvent(MouseEvent) : void |
| onKeyEvent(KeyEvent) : void |
--------------------4.代码
#include iostream
#include map// 定义事件类型
enum class EventType {MouseClick,KeyPress
};// 定义鼠标事件信息
struct MouseEvent {int x, y;int button;bool pressed;
};// 定义键盘事件信息
struct KeyEvent {int key;
};// 事件回调函数指针类型
using MouseCallback void (*)(const MouseEvent);
using KeyCallback void (*)(const KeyEvent);// 抽象相机控制器基类
class CameraControl {
public:virtual void handleMouseEvent(const MouseEvent event) 0;virtual void handleKeyEvent(const KeyEvent event) 0;virtual void update() 0;
};// 一个简单的相机控制器实现
class SimpleCameraControl : public CameraControl {
public:void handleMouseEvent(const MouseEvent event) override {if (event.pressed) {mousePressed true;lastX event.x;lastY event.y;std::cout Mouse button event.button pressed at ( event.x , event.y )\n;} else {mousePressed false;double deltaX event.x - lastX;double deltaY event.y - lastY;std::cout Mouse dragged by ( deltaX , deltaY )\n;lastX event.x;lastY event.y;}}void handleKeyEvent(const KeyEvent event) override {keys[event.key] true;std::cout Key pressed: event.key \n;}void update() override {std::cout Updating camera control\n;}private:bool mousePressed false;double lastX 0.0, lastY 0.0;std::mapint, bool keys;
};// 应用程序类
class Application {
public:Application(): cameraControl(new SimpleCameraControl()) {}void setMouseCallback(MouseCallback callback) {mouseCallback callback;}void setKeyCallback(KeyCallback callback) {keyCallback callback;}void triggerMouseEvent(const MouseEvent event) {if (mouseCallback) {mouseCallback(event);}}void triggerKeyEvent(const KeyEvent event) {if (keyCallback) {keyCallback(event);}}void run() {// 模拟事件触发triggerMouseEvent(MouseEvent{100, 200, 1, true});triggerMouseEvent(MouseEvent{150, 250, 1, false});triggerKeyEvent(KeyEvent{65});// 更新相机控制cameraControl-update();}private:SimpleCameraControl* cameraControl;MouseCallback mouseCallback nullptr;KeyCallback keyCallback nullptr;
};// 全局函数
void onMouseEvent(const MouseEvent event) {static SimpleCameraControl control;control.handleMouseEvent(event);
}void onKeyEvent(const KeyEvent event) {static SimpleCameraControl control;control.handleKeyEvent(event);
}int main() {Application app;app.setMouseCallback(onMouseEvent);app.setKeyCallback(onKeyEvent);app.run();return 0;
}