ScreenLockDetector/docs/UNIFIED_RENDERING_QUICKSTAR...

9.5 KiB
Raw Blame History

统一渲染架构快速入门

概述

本项目采用统一的渲染架构设计,通过抽象基类 RenderWidgetBase 实现对 Vulkan 和 QPainter 两种渲染方式的统一管理。

核心设计

三层架构

┌─────────────────────────────────────┐
│         MainWindow                  │  ← 使用统一接口
│  (RenderWidgetBase* m_renderWidget) │
└──────────────┬──────────────────────┘
               │
               ↓
┌─────────────────────────────────────┐
│      RenderWidgetBase (基类)        │  ← 定义统一接口
│   - initializeRenderer()            │
│   - setRenderingEnabled()           │
│   - getRenderFrameCount()           │
│   - getRendererType()               │
└──────────────┬──────────────────────┘
               │
       ┌───────┴────────┐
       ↓                ↓
┌─────────────┐  ┌─────────────┐
│VulkanWidget │  │CustomWidget │        ← 具体实现
│  (Vulkan)   │  │ (QPainter)  │
└─────────────┘  └─────────────┘

编译选项

使用 Vulkan默认如果可用

cd ScreenLockDetector
mkdir -p build && cd build
cmake .. -DENABLE_VULKAN=ON
make -j4

结果:应用将使用 VulkanWidget 进行硬件加速渲染

使用 QPainter后备方案

cd ScreenLockDetector
mkdir -p build && cd build
cmake .. -DENABLE_VULKAN=OFF
make -j4

结果:应用将使用 CustomWidget 进行 CPU 绘制

自动回退

如果 Vulkan 头文件不可用CMake 会自动回退到 QPainter

cmake ..
# 输出Vulkan headers not found, disabling Vulkan support

主要改进

之前的设计问题

// ❌ 旧设计:需要维护两个独立的组件
private:
    CustomWidget *m_customWidget;
    #ifdef ENABLE_VULKAN_WIDGET
    VulkanWidget *m_vulkanWidget;
    #endif
    
    QTabWidget *m_tabWidget;  // 使用 Tab 切换

新的统一设计

// ✅ 新设计:单一组件指针
private:
    RenderWidgetBase *m_renderWidget;  // 统一接口
    
    // 构造函数中根据编译选项创建
    #ifdef ENABLE_VULKAN_WIDGET
        m_renderWidget = new VulkanWidget(this);
    #else
        m_renderWidget = new CustomWidget(this);
    #endif

统一接口使用示例

1. 初始化渲染器

// 对于 VulkanWidget内部调用 initializeVulkan()
// 对于 CustomWidget直接返回 true无需初始化
bool success = m_renderWidget->initializeRenderer();
if (!success) {
    qDebug() << "Error:" << m_renderWidget->getLastError();
}

2. 控制渲染

// 启用渲染(适用于任何渲染器)
m_renderWidget->setRenderingEnabled(true);

// 禁用渲染(适用于任何渲染器)
m_renderWidget->setRenderingEnabled(false);

// 查询状态
bool isRendering = m_renderWidget->isRenderingEnabled();

3. 获取状态信息

// 获取渲染器类型
QString type = m_renderWidget->getRendererType();
// 返回 "Vulkan" 或 "QPainter"

// 获取帧数统计
int frames = m_renderWidget->getRenderFrameCount();

// 检查初始化状态
bool initialized = m_renderWidget->isInitialized();

4. 错误处理

if (!m_renderWidget->isInitialized()) {
    if (!m_renderWidget->initializeRenderer()) {
        QMessageBox::warning(
            this, 
            "初始化失败",
            m_renderWidget->getLastError()
        );
    }
}

锁屏检测集成

无论使用哪种渲染器,锁屏检测的处理逻辑完全一致:

void MainWindow::onLockStateChanged(bool locked)
{
    // 统一的处理逻辑
    if (m_renderWidget) {
        m_renderWidget->setRenderingEnabled(!locked);
    }
    
    updateStatusDisplay();
    updateButtonStates();
}

添加新渲染器

假设要添加 OpenGL 支持:

1. 创建新类

// src/openglwidget.h
class OpenGLWidget : public RenderWidgetBase
{
    Q_OBJECT
public:
    explicit OpenGLWidget(QWidget *parent = nullptr);
    
    // 实现所有虚函数
    bool initializeRenderer() override;
    void setRenderingEnabled(bool enabled) override;
    bool isRenderingEnabled() const override;
    int getRenderFrameCount() const override;
    void resetFrameCount() override;
    bool isInitialized() const override;
    QString getLastError() const override;
    QString getRendererType() const override { return "OpenGL"; }
};

2. 修改 CMakeLists.txt

option(ENABLE_OPENGL "Enable OpenGL support" OFF)

if(ENABLE_OPENGL)
    list(APPEND SOURCES src/openglwidget.cpp)
    list(APPEND HEADERS src/openglwidget.h)
    add_definitions(-DENABLE_OPENGL_WIDGET)
endif()

3. 修改 MainWindow 构造函数

#ifdef ENABLE_VULKAN_WIDGET
    m_renderWidget = new VulkanWidget(this);
#elif defined(ENABLE_OPENGL_WIDGET)
    m_renderWidget = new OpenGLWidget(this);
#else
    m_renderWidget = new CustomWidget(this);
#endif

运行效果

Vulkan 模式

┌──────────────────────────────────────┐
│  Qt Screen Lock Detection Demo       │
├──────────────────────────────────────┤
│                                      │
│   [Vulkan 硬件加速渲染窗口]          │
│    (旋转的彩色圆圈动画)              │
│                                      │
├──────────────────────────────────────┤
│  [ Enable Rendering ]                │
│  [ Disable Rendering ]               │
│  [ Reset Frame Count ]               │
├──────────────────────────────────────┤
│  Renderer Type: Vulkan               │
│  Detector Status: Active             │
│  Renderer Status: ✓ Initialized      │
│  Screen Lock Status: 🔓 UNLOCKED     │
│  Rendering Status: ✓ ENABLED         │
│  Frame Count: 1234 frames            │
└──────────────────────────────────────┘

QPainter 模式

┌──────────────────────────────────────┐
│  Qt Screen Lock Detection Demo       │
├──────────────────────────────────────┤
│                                      │
│   [QPainter 2D 渲染窗口]             │
│    (旋转的彩色圆圈动画)              │
│                                      │
├──────────────────────────────────────┤
│  [ Enable Rendering ]                │
│  [ Disable Rendering ]               │
│  [ Reset Frame Count ]               │
├──────────────────────────────────────┤
│  Renderer Type: QPainter             │
│  Detector Status: Active             │
│  Renderer Status: ✓ Initialized      │
│  Screen Lock Status: 🔓 UNLOCKED     │
│  Rendering Status: ✓ ENABLED         │
│  Frame Count: 1234 frames            │
└──────────────────────────────────────┘

优势总结

代码简化

  • MainWindow 代码减少约 40%
  • 消除了大量重复的控制逻辑
  • 减少了条件编译代码

统一界面

  • 不再使用 Tab 切换
  • 单一、简洁的用户界面
  • 自动选择最佳渲染方式

易于维护

  • 添加新功能只需修改基类接口
  • 所有实现类自动继承新接口
  • 更容易追踪和修复 bug

高可扩展性

  • 可以轻松添加新的渲染后端
  • 可以在运行时切换渲染器(未来功能)
  • 支持插件化架构(未来功能)

常见问题

Q: 如何知道当前使用的是哪种渲染器?

A: 查看应用程序窗口的 "Renderer Type" 标签,或在日志中查看:

MainWindow initialized with Vulkan renderer

Q: Vulkan 初始化失败怎么办?

A: 应用会自动显示错误信息。可以重新编译使用 QPainter

cmake .. -DENABLE_VULKAN=OFF
make -j4

Q: 两种渲染器性能差异大吗?

A:

  • Vulkan: 硬件加速GPU 渲染CPU 占用低,适合复杂场景
  • QPainter: CPU 渲染CPU 占用较高,但兼容性最好

Q: 可以在运行时切换渲染器吗?

A: 当前版本不支持,但架构设计已经为此功能预留了空间。

相关文档

贡献指南

如果您想添加新的渲染后端:

  1. 创建新类继承 RenderWidgetBase
  2. 实现所有虚函数
  3. 在 CMakeLists.txt 中添加编译选项
  4. 在 MainWindow 中添加创建逻辑
  5. 编写测试用例
  6. 更新文档

欢迎提交 Pull Request