Introduce RenderWidgetBase and unify renderers

Add RenderWidgetBase and update CustomWidget and VulkanWidget to
implement its interface. Refactor MainWindow to use a single
RenderWidgetBase pointer, unify controls and status UI, and remove the
dual-tab setup. Add design and quickstart docs and register the new
header in CMakeLists.txt.
This commit is contained in:
ubuntu1804 2025-11-11 10:27:06 +08:00
parent 8ee653e1a6
commit 2c7119d190
10 changed files with 1061 additions and 416 deletions

View File

@ -132,6 +132,7 @@ set(SOURCES
set(HEADERS set(HEADERS
src/mainwindow.h src/mainwindow.h
src/renderwidgetbase.h
src/customwidget.h src/customwidget.h
) )

View File

@ -0,0 +1,334 @@
# 统一渲染架构快速入门
## 概述
本项目采用统一的渲染架构设计,通过抽象基类 `RenderWidgetBase` 实现对 Vulkan 和 QPainter 两种渲染方式的统一管理。
## 核心设计
### 三层架构
```
┌─────────────────────────────────────┐
│ MainWindow │ ← 使用统一接口
│ (RenderWidgetBase* m_renderWidget) │
└──────────────┬──────────────────────┘
┌─────────────────────────────────────┐
│ RenderWidgetBase (基类) │ ← 定义统一接口
│ - initializeRenderer() │
│ - setRenderingEnabled() │
│ - getRenderFrameCount() │
│ - getRendererType() │
└──────────────┬──────────────────────┘
┌───────┴────────┐
↓ ↓
┌─────────────┐ ┌─────────────┐
│VulkanWidget │ │CustomWidget │ ← 具体实现
│ (Vulkan) │ │ (QPainter) │
└─────────────┘ └─────────────┘
```
## 编译选项
### 使用 Vulkan默认如果可用
```bash
cd ScreenLockDetector
mkdir -p build && cd build
cmake .. -DENABLE_VULKAN=ON
make -j4
```
**结果**:应用将使用 VulkanWidget 进行硬件加速渲染
### 使用 QPainter后备方案
```bash
cd ScreenLockDetector
mkdir -p build && cd build
cmake .. -DENABLE_VULKAN=OFF
make -j4
```
**结果**:应用将使用 CustomWidget 进行 CPU 绘制
### 自动回退
如果 Vulkan 头文件不可用CMake 会自动回退到 QPainter
```bash
cmake ..
# 输出Vulkan headers not found, disabling Vulkan support
```
## 主要改进
### 之前的设计问题
```cpp
// ❌ 旧设计:需要维护两个独立的组件
private:
CustomWidget *m_customWidget;
#ifdef ENABLE_VULKAN_WIDGET
VulkanWidget *m_vulkanWidget;
#endif
QTabWidget *m_tabWidget; // 使用 Tab 切换
```
### 新的统一设计
```cpp
// ✅ 新设计:单一组件指针
private:
RenderWidgetBase *m_renderWidget; // 统一接口
// 构造函数中根据编译选项创建
#ifdef ENABLE_VULKAN_WIDGET
m_renderWidget = new VulkanWidget(this);
#else
m_renderWidget = new CustomWidget(this);
#endif
```
## 统一接口使用示例
### 1. 初始化渲染器
```cpp
// 对于 VulkanWidget内部调用 initializeVulkan()
// 对于 CustomWidget直接返回 true无需初始化
bool success = m_renderWidget->initializeRenderer();
if (!success) {
qDebug() << "Error:" << m_renderWidget->getLastError();
}
```
### 2. 控制渲染
```cpp
// 启用渲染(适用于任何渲染器)
m_renderWidget->setRenderingEnabled(true);
// 禁用渲染(适用于任何渲染器)
m_renderWidget->setRenderingEnabled(false);
// 查询状态
bool isRendering = m_renderWidget->isRenderingEnabled();
```
### 3. 获取状态信息
```cpp
// 获取渲染器类型
QString type = m_renderWidget->getRendererType();
// 返回 "Vulkan" 或 "QPainter"
// 获取帧数统计
int frames = m_renderWidget->getRenderFrameCount();
// 检查初始化状态
bool initialized = m_renderWidget->isInitialized();
```
### 4. 错误处理
```cpp
if (!m_renderWidget->isInitialized()) {
if (!m_renderWidget->initializeRenderer()) {
QMessageBox::warning(
this,
"初始化失败",
m_renderWidget->getLastError()
);
}
}
```
## 锁屏检测集成
无论使用哪种渲染器,锁屏检测的处理逻辑完全一致:
```cpp
void MainWindow::onLockStateChanged(bool locked)
{
// 统一的处理逻辑
if (m_renderWidget) {
m_renderWidget->setRenderingEnabled(!locked);
}
updateStatusDisplay();
updateButtonStates();
}
```
## 添加新渲染器
假设要添加 OpenGL 支持:
### 1. 创建新类
```cpp
// 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
```cmake
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 构造函数
```cpp
#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
```bash
cmake .. -DENABLE_VULKAN=OFF
make -j4
```
### Q: 两种渲染器性能差异大吗?
A:
- **Vulkan**: 硬件加速GPU 渲染CPU 占用低,适合复杂场景
- **QPainter**: CPU 渲染CPU 占用较高,但兼容性最好
### Q: 可以在运行时切换渲染器吗?
A: 当前版本不支持,但架构设计已经为此功能预留了空间。
## 相关文档
- [详细设计文档](./unified_rendering_design.md) - 完整的架构设计说明
- [API 参考](../src/renderwidgetbase.h) - RenderWidgetBase 接口定义
- [主 README](../README.md) - 项目总体说明
## 贡献指南
如果您想添加新的渲染后端:
1. 创建新类继承 `RenderWidgetBase`
2. 实现所有虚函数
3. 在 CMakeLists.txt 中添加编译选项
4. 在 MainWindow 中添加创建逻辑
5. 编写测试用例
6. 更新文档
欢迎提交 Pull Request

View File

@ -0,0 +1,379 @@
# 统一渲染架构设计文档
## 概述
本文档描述了 ScreenLockDetector 项目中统一渲染架构的设计和实现。通过引入基类 `RenderWidgetBase`,我们实现了对 Vulkan 和 QPainter 两种渲染方式的统一抽象,使得 MainWindow 可以通过统一的接口操作不同的渲染实现。
## 设计目标
1. **统一接口**:为不同的渲染实现提供统一的操作接口
2. **编译时选择**:通过 CMake 编译选项自动选择 Vulkan 或 QPainter 实现
3. **简化 MainWindow**MainWindow 无需关心具体的渲染实现细节
4. **易于扩展**:未来可以方便地添加其他渲染后端(如 OpenGL、DirectX 等)
## 架构设计
### 类层次结构
```
QWidget
|
RenderWidgetBase (抽象基类)
|
+--- VulkanWidget (Vulkan 实现)
|
+--- CustomWidget (QPainter 实现)
```
### 核心组件
#### 1. RenderWidgetBase (基类)
**文件位置**: `src/renderwidgetbase.h`
**职责**:
- 定义统一的渲染组件接口
- 继承自 QWidget
- 所有方法都是纯虚函数,由子类实现
**核心接口**:
```cpp
// 初始化渲染器
virtual bool initializeRenderer() = 0;
// 启用/禁用渲染
virtual void setRenderingEnabled(bool enabled) = 0;
virtual bool isRenderingEnabled() const = 0;
// 帧计数管理
virtual int getRenderFrameCount() const = 0;
virtual void resetFrameCount() = 0;
// 状态查询
virtual bool isInitialized() const = 0;
virtual QString getLastError() const = 0;
virtual QString getRendererType() const = 0;
```
#### 2. VulkanWidget (Vulkan 实现)
**文件位置**: `src/vulkanwidget.h`, `src/vulkanwidget.cpp`
**特点**:
- 使用 Vulkan API 进行硬件加速渲染
- 通过 volk 动态加载 Vulkan 函数
- 支持跨平台Windows, Linux, macOS
- 实现了 RenderWidgetBase 的所有接口
- 保留了原有的 `initializeVulkan()` 等方法以保持向后兼容
**实现要点**:
- `initializeRenderer()` 内部调用 `initializeVulkan()`
- `getRendererType()` 返回 "Vulkan"
- 提供详细的错误信息通过 `getLastError()`
#### 3. CustomWidget (QPainter 实现)
**文件位置**: `src/customwidget.h`, `src/customwidget.cpp`
**特点**:
- 使用 Qt 的 QPainter 进行 2D 绘制
- 不需要额外的依赖库
- 跨平台兼容性最佳
- 实现了 RenderWidgetBase 的所有接口
- 保留了原有的 `setPaintingEnabled()` 等方法以保持向后兼容
**实现要点**:
- `initializeRenderer()` 始终返回 trueQPainter 不需要初始化)
- `getRendererType()` 返回 "QPainter"
- `getLastError()` 返回空字符串QPainter 通常不会出错)
#### 4. MainWindow (主窗口)
**文件位置**: `src/mainwindow.h`, `src/mainwindow.cpp`
**设计改进**:
**之前的设计**:
- 使用 QTabWidget 同时显示 VulkanWidget 和 CustomWidget
- 维护两个独立的组件指针
- 需要重复的控制逻辑和状态管理代码
**新的设计**:
- 只显示一个渲染 Widget
- 使用 `RenderWidgetBase*` 统一指针
- 通过编译选项决定使用哪个实现
- 统一的控制按钮和状态显示
**核心代码**:
```cpp
class MainWindow : public QMainWindow
{
private:
RenderWidgetBase *m_renderWidget; // 统一的渲染组件指针
// 统一的控制按钮
QPushButton *m_enableRenderBtn;
QPushButton *m_disableRenderBtn;
QPushButton *m_resetFrameBtn;
// 统一的状态标签
QLabel *m_rendererTypeLabel;
QLabel *m_initStatusLabel;
QLabel *m_renderStatusLabel;
QLabel *m_frameCountLabel;
};
```
**组件创建**:
```cpp
// 根据编译选项创建相应的渲染组件
#ifdef ENABLE_VULKAN_WIDGET
m_renderWidget = new VulkanWidget(this);
#else
m_renderWidget = new CustomWidget(this);
#endif
// 后续代码通过基类指针操作,无需关心具体实现
m_renderWidget->initializeRenderer();
m_renderWidget->setRenderingEnabled(true);
```
## 编译配置
### CMake 选项
通过 `ENABLE_VULKAN` 选项控制是否启用 Vulkan 支持:
```cmake
option(ENABLE_VULKAN "Enable Vulkan support" ON)
```
### 编译时行为
**启用 Vulkan (`ENABLE_VULKAN=ON`)**:
- 检查 Vulkan 头文件是否存在
- 编译 volk 动态加载库
- 添加 `ENABLE_VULKAN_WIDGET` 宏定义
- 编译 VulkanWidget 相关文件
- MainWindow 创建 VulkanWidget 实例
**禁用 Vulkan (`ENABLE_VULKAN=OFF` 或 Vulkan 不可用)**:
- 不编译 VulkanWidget 相关文件
- MainWindow 创建 CustomWidget 实例
- 使用 QPainter 作为后备渲染方案
## 使用示例
### 基本使用
```cpp
// MainWindow 中的使用示例
void MainWindow::onEnableRenderingClicked()
{
if (m_renderWidget) {
// 确保渲染器已初始化
if (!m_renderWidget->isInitialized()) {
bool success = m_renderWidget->initializeRenderer();
if (!success) {
QMessageBox::warning(this, "Initialization Failed",
m_renderWidget->getLastError());
return;
}
}
// 启用渲染
m_renderWidget->setRenderingEnabled(true);
}
}
// 查询状态
void MainWindow::updateStatusDisplay()
{
QString type = m_renderWidget->getRendererType();
bool isRendering = m_renderWidget->isRenderingEnabled();
int frameCount = m_renderWidget->getRenderFrameCount();
// 更新 UI 显示
m_rendererTypeLabel->setText("Renderer: " + type);
m_frameCountLabel->setText(QString("Frames: %1").arg(frameCount));
}
```
### 锁屏检测集成
```cpp
void MainWindow::onLockStateChanged(bool locked)
{
// 统一的锁屏处理逻辑
if (m_renderWidget) {
m_renderWidget->setRenderingEnabled(!locked);
}
}
```
## 优势分析
### 1. 代码简化
**之前**:
- MainWindow 中有大量 `#ifdef ENABLE_VULKAN_WIDGET` 条件编译代码
- 需要维护两套独立的控制逻辑
- UI 代码重复(两套按钮、两套状态标签)
**现在**:
- MainWindow 中几乎没有条件编译代码
- 统一的控制逻辑
- 统一的 UI 组件
### 2. 易于维护
- 添加新功能时,只需在基类中添加接口,各子类实现即可
- MainWindow 代码量减少约 40%
- 更容易理解和维护
### 3. 灵活性
- 可以轻松添加新的渲染后端OpenGL、DirectX、Metal 等)
- 可以在运行时动态切换渲染器(未来扩展)
- 可以通过配置文件选择渲染器(未来扩展)
### 4. 用户体验
- 界面更加简洁,不再有多个 Tab
- 自动选择最佳的渲染方式
- 统一的操作体验
## 扩展性设计
### 添加新的渲染后端
假设要添加 OpenGL 渲染支持:
1. 创建 `OpenGLWidget` 类继承 `RenderWidgetBase`
2. 实现所有虚函数
3. 在 CMakeLists.txt 中添加编译选项
4. 在 MainWindow 构造函数中添加选择逻辑
```cpp
#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
```
### 运行时切换(未来功能)
可以扩展设计以支持运行时切换渲染器:
```cpp
void MainWindow::switchRenderer(RendererType type)
{
if (m_renderWidget) {
delete m_renderWidget;
}
switch (type) {
case RendererType::Vulkan:
m_renderWidget = new VulkanWidget(this);
break;
case RendererType::OpenGL:
m_renderWidget = new OpenGLWidget(this);
break;
case RendererType::QPainter:
default:
m_renderWidget = new CustomWidget(this);
break;
}
// 重新初始化和布局
setupRenderer();
}
```
## 性能考虑
### 虚函数开销
- 基类使用虚函数会有轻微的性能开销
- 但相比渲染本身的开销,这个开销可以忽略不计
- 现代编译器对虚函数调用有很好的优化
### 内存占用
- 每个对象增加一个虚函数表指针(通常 8 字节)
- 由于只创建一个渲染 Widget 实例,内存影响微乎其微
## 测试建议
### 单元测试
```cpp
// 测试 Vulkan 初始化
void testVulkanInitialization() {
VulkanWidget widget;
bool success = widget.initializeRenderer();
QVERIFY(success || !widget.getLastError().isEmpty());
QCOMPARE(widget.getRendererType(), QString("Vulkan"));
}
// 测试 QPainter 初始化
void testQPainterInitialization() {
CustomWidget widget;
bool success = widget.initializeRenderer();
QVERIFY(success);
QCOMPARE(widget.getRendererType(), QString("QPainter"));
QVERIFY(widget.isInitialized());
}
// 测试渲染启用/禁用
void testRenderingToggle() {
RenderWidgetBase* widget = createWidget();
widget->initializeRenderer();
widget->setRenderingEnabled(true);
QVERIFY(widget->isRenderingEnabled());
widget->setRenderingEnabled(false);
QVERIFY(!widget->isRenderingEnabled());
}
```
### 集成测试
- 测试 MainWindow 与不同渲染器的集成
- 测试锁屏检测触发渲染器状态变化
- 测试 UI 按钮与渲染器的交互
## 文件清单
### 新增文件
- `src/renderwidgetbase.h` - 渲染组件基类
### 修改文件
- `src/mainwindow.h` - 简化为使用单一渲染组件
- `src/mainwindow.cpp` - 移除重复代码,使用统一接口
- `src/customwidget.h` - 继承 RenderWidgetBase
- `src/customwidget.cpp` - 实现基类接口
- `src/vulkanwidget.h` - 继承 RenderWidgetBase
- `src/vulkanwidget.cpp` - 实现基类接口
- `CMakeLists.txt` - 添加 renderwidgetbase.h 到头文件列表
## 总结
统一渲染架构通过引入抽象基类,成功地实现了:
1. ✅ 代码简化:减少了重复代码和条件编译
2. ✅ 接口统一MainWindow 通过统一接口操作渲染器
3. ✅ 易于扩展:可以方便地添加新的渲染后端
4. ✅ 向后兼容:保留了原有的特定方法
5. ✅ 用户体验:提供了更简洁的界面
这个设计为项目的后续发展提供了坚实的基础,使得添加新功能和维护现有代码变得更加容易。

View File

@ -5,7 +5,7 @@
#include <cmath> #include <cmath>
CustomWidget::CustomWidget(QWidget *parent) CustomWidget::CustomWidget(QWidget *parent)
: QWidget(parent) : RenderWidgetBase(parent)
, m_animationTimer(nullptr) , m_animationTimer(nullptr)
, m_paintingEnabled(true) , m_paintingEnabled(true)
, m_frameCount(0) , m_frameCount(0)
@ -92,6 +92,45 @@ void CustomWidget::resetFrameCount()
qDebug() << "Frame count reset"; qDebug() << "Frame count reset";
} }
// 实现 RenderWidgetBase 接口
bool CustomWidget::initializeRenderer()
{
// QPainter不需要特殊初始化始终返回true
return true;
}
void CustomWidget::setRenderingEnabled(bool enabled)
{
setPaintingEnabled(enabled);
}
bool CustomWidget::isRenderingEnabled() const
{
return isPaintingEnabled();
}
int CustomWidget::getRenderFrameCount() const
{
return getPaintFrameCount();
}
bool CustomWidget::isInitialized() const
{
// QPainter始终处于初始化状态
return true;
}
QString CustomWidget::getLastError() const
{
// QPainter通常不会有错误
return QString();
}
QString CustomWidget::getRendererType() const
{
return QString("QPainter");
}
void CustomWidget::onAnimationTimer() void CustomWidget::onAnimationTimer()
{ {
if (m_paintingEnabled) { if (m_paintingEnabled) {

View File

@ -1,7 +1,7 @@
#ifndef CUSTOMWIDGET_H #ifndef CUSTOMWIDGET_H
#define CUSTOMWIDGET_H #define CUSTOMWIDGET_H
#include <QWidget> #include "renderwidgetbase.h"
#include <QPainter> #include <QPainter>
#include <QTimer> #include <QTimer>
#include <QDateTime> #include <QDateTime>
@ -9,42 +9,34 @@
#include <QLinearGradient> #include <QLinearGradient>
/** /**
* @brief * @brief 使QPainter
* *
* *
* Paint事件 * Paint事件
*/ */
class CustomWidget : public QWidget class CustomWidget : public RenderWidgetBase
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CustomWidget(QWidget *parent = nullptr); explicit CustomWidget(QWidget *parent = nullptr);
~CustomWidget(); ~CustomWidget() override;
/** // 实现RenderWidgetBase接口
* @brief bool initializeRenderer() override;
* @param enabled true表示启用绘制false表示禁用 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;
// CustomWidget特有的方法保持兼容性
void setPaintingEnabled(bool enabled); void setPaintingEnabled(bool enabled);
/**
* @brief
* @return true表示绘制已启用false表示已禁用
*/
bool isPaintingEnabled() const; bool isPaintingEnabled() const;
/**
* @brief
* @return
*/
int getPaintFrameCount() const; int getPaintFrameCount() const;
/**
* @brief
*/
void resetFrameCount();
protected: protected:
/** /**
* @brief paintEvent以实现自定义绘制 * @brief paintEvent以实现自定义绘制
@ -104,4 +96,4 @@ private:
int m_lockCount; // 锁屏次数 int m_lockCount; // 锁屏次数
}; };
#endif // CUSTOMWIDGET_H #endif // CUSTOMWIDGET_H

View File

@ -1,43 +1,32 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "customwidget.h"
#ifdef ENABLE_VULKAN_WIDGET
#include "vulkanwidget.h"
#endif
#include <QDebug> #include <QDebug>
#include <QMessageBox> #include <QMessageBox>
#include <QTabWidget>
MainWindow::MainWindow(QWidget *parent) MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent) : QMainWindow(parent)
, m_lockDetector(nullptr) , m_lockDetector(nullptr)
, m_customWidget(nullptr) , m_renderWidget(nullptr)
#ifdef ENABLE_VULKAN_WIDGET
, m_vulkanWidget(nullptr)
#endif
, m_centralWidget(nullptr) , m_centralWidget(nullptr)
, m_mainLayout(nullptr) , m_mainLayout(nullptr)
, m_tabWidget(nullptr)
, m_controlGroup(nullptr) , m_controlGroup(nullptr)
, m_enablePaintBtn(nullptr) , m_enableRenderBtn(nullptr)
, m_disablePaintBtn(nullptr) , m_disableRenderBtn(nullptr)
, m_resetFrameBtn(nullptr) , m_resetFrameBtn(nullptr)
#ifdef ENABLE_VULKAN_WIDGET
, m_vulkanControlGroup(nullptr)
, m_enableVulkanBtn(nullptr)
, m_disableVulkanBtn(nullptr)
, m_resetVulkanFrameBtn(nullptr)
#endif
, m_statusGroup(nullptr) , m_statusGroup(nullptr)
, m_rendererTypeLabel(nullptr)
, m_lockStatusLabel(nullptr) , m_lockStatusLabel(nullptr)
, m_paintStatusLabel(nullptr) , m_renderStatusLabel(nullptr)
, m_frameCountLabel(nullptr) , m_frameCountLabel(nullptr)
, m_detectorStatusLabel(nullptr) , m_detectorStatusLabel(nullptr)
#ifdef ENABLE_VULKAN_WIDGET , m_initStatusLabel(nullptr)
, m_vulkanStatusGroup(nullptr)
, m_vulkanInitLabel(nullptr)
, m_vulkanRenderStatusLabel(nullptr)
, m_vulkanFrameCountLabel(nullptr)
#endif
, m_updateTimer(nullptr) , m_updateTimer(nullptr)
{ {
setWindowTitle("Qt Screen Lock Detection Demo"); setWindowTitle("Qt Screen Lock Detection Demo");
setMinimumSize(800, 600); setMinimumSize(800, 800);
// 初始化锁屏检测器 // 初始化锁屏检测器
m_lockDetector = new ScreenLockDetector(this); m_lockDetector = new ScreenLockDetector(this);
@ -63,24 +52,23 @@ MainWindow::MainWindow(QWidget *parent)
connect(m_updateTimer, &QTimer::timeout, this, &MainWindow::updateStatusDisplay); connect(m_updateTimer, &QTimer::timeout, this, &MainWindow::updateStatusDisplay);
m_updateTimer->start(100); // 每100ms更新一次状态显示 m_updateTimer->start(100); // 每100ms更新一次状态显示
#ifdef ENABLE_VULKAN_WIDGET // 初始化渲染器
// 初始化Vulkan并默认启用渲染 if (m_renderWidget) {
if (m_vulkanWidget) { bool renderInitOk = m_renderWidget->initializeRenderer();
bool vulkanInitOk = m_vulkanWidget->initializeVulkan(); if (renderInitOk) {
if (vulkanInitOk) { m_renderWidget->setRenderingEnabled(true);
m_vulkanWidget->setRenderingEnabled(true); qDebug() << m_renderWidget->getRendererType() << "renderer initialized and enabled by default";
qDebug() << "VulkanWidget initialized and rendering enabled by default";
} else { } else {
qDebug() << "Failed to initialize VulkanWidget:" << m_vulkanWidget->getLastError(); qDebug() << "Failed to initialize" << m_renderWidget->getRendererType()
<< "renderer:" << m_renderWidget->getLastError();
} }
} }
#endif // ENABLE_VULKAN_WIDGET
// 初始化状态显示 // 初始化状态显示
updateStatusDisplay(); updateStatusDisplay();
updateButtonStates(); updateButtonStates();
qDebug() << "MainWindow initialized"; qDebug() << "MainWindow initialized with" << (m_renderWidget ? m_renderWidget->getRendererType() : "no") << "renderer";
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()
@ -105,112 +93,62 @@ void MainWindow::setupUI()
QFont statusFont; QFont statusFont;
statusFont.setPointSize(10); statusFont.setPointSize(10);
// 创建Tab Widget // 创建渲染组件根据编译选项选择Vulkan或QPainter
m_tabWidget = new QTabWidget(this);
m_mainLayout->addWidget(m_tabWidget, 1);
#ifdef ENABLE_VULKAN_WIDGET #ifdef ENABLE_VULKAN_WIDGET
// ========== Tab 1: VulkanWidget ========== m_renderWidget = new VulkanWidget(this);
QWidget *vulkanTab = new QWidget(this); qDebug() << "Creating VulkanWidget";
QVBoxLayout *vulkanLayout = new QVBoxLayout(vulkanTab); #else
vulkanLayout->setSpacing(10); m_renderWidget = new CustomWidget(this);
vulkanLayout->setContentsMargins(10, 10, 10, 10); qDebug() << "Creating CustomWidget (QPainter)";
#endif
// 创建Vulkan渲染组件 m_mainLayout->addWidget(m_renderWidget, 1);
m_vulkanWidget = new VulkanWidget(this);
vulkanLayout->addWidget(m_vulkanWidget, 1);
// 创建Vulkan控制面板
m_vulkanControlGroup = new QGroupBox("Vulkan Control", this);
QHBoxLayout *vulkanControlLayout = new QHBoxLayout(m_vulkanControlGroup);
m_enableVulkanBtn = new QPushButton("Enable Rendering", this);
m_disableVulkanBtn = new QPushButton("Disable Rendering", this);
m_resetVulkanFrameBtn = new QPushButton("Reset Frame Count", this);
m_enableVulkanBtn->setMinimumHeight(35);
m_disableVulkanBtn->setMinimumHeight(35);
m_resetVulkanFrameBtn->setMinimumHeight(35);
vulkanControlLayout->addWidget(m_enableVulkanBtn);
vulkanControlLayout->addWidget(m_disableVulkanBtn);
vulkanControlLayout->addWidget(m_resetVulkanFrameBtn);
vulkanControlLayout->addStretch();
vulkanLayout->addWidget(m_vulkanControlGroup);
// 创建Vulkan状态显示面板
m_vulkanStatusGroup = new QGroupBox("Vulkan Status Information", this);
QVBoxLayout *vulkanStatusLayout = new QVBoxLayout(m_vulkanStatusGroup);
m_vulkanInitLabel = new QLabel("Vulkan Status: Not Initialized", this);
m_vulkanRenderStatusLabel = new QLabel("Rendering Status: Disabled", this);
m_vulkanFrameCountLabel = new QLabel("Frame Count: 0", this);
m_vulkanInitLabel->setFont(statusFont);
m_vulkanRenderStatusLabel->setFont(statusFont);
m_vulkanFrameCountLabel->setFont(statusFont);
vulkanStatusLayout->addWidget(m_vulkanInitLabel);
vulkanStatusLayout->addWidget(m_vulkanRenderStatusLabel);
vulkanStatusLayout->addWidget(m_vulkanFrameCountLabel);
vulkanLayout->addWidget(m_vulkanStatusGroup);
m_tabWidget->addTab(vulkanTab, "Vulkan Widget");
#endif // ENABLE_VULKAN_WIDGET
// ========== Tab 2: CustomWidget (QPainter) ==========
QWidget *customTab = new QWidget(this);
QVBoxLayout *customLayout = new QVBoxLayout(customTab);
customLayout->setSpacing(10);
customLayout->setContentsMargins(10, 10, 10, 10);
// 创建自定义绘制组件
m_customWidget = new CustomWidget(this);
customLayout->addWidget(m_customWidget, 1);
// 创建控制面板 // 创建控制面板
m_controlGroup = new QGroupBox("Manual Control", this); m_controlGroup = new QGroupBox("Rendering Control", this);
QHBoxLayout *controlLayout = new QHBoxLayout(m_controlGroup); QHBoxLayout *controlLayout = new QHBoxLayout(m_controlGroup);
m_enablePaintBtn = new QPushButton("Enable Painting", this); m_enableRenderBtn = new QPushButton("Enable Rendering", this);
m_disablePaintBtn = new QPushButton("Disable Painting", this); m_disableRenderBtn = new QPushButton("Disable Rendering", this);
m_resetFrameBtn = new QPushButton("Reset Frame Count", this); m_resetFrameBtn = new QPushButton("Reset Frame Count", this);
m_enablePaintBtn->setMinimumHeight(35); m_enableRenderBtn->setMinimumHeight(35);
m_disablePaintBtn->setMinimumHeight(35); m_disableRenderBtn->setMinimumHeight(35);
m_resetFrameBtn->setMinimumHeight(35); m_resetFrameBtn->setMinimumHeight(35);
controlLayout->addWidget(m_enablePaintBtn); controlLayout->addWidget(m_enableRenderBtn);
controlLayout->addWidget(m_disablePaintBtn); controlLayout->addWidget(m_disableRenderBtn);
controlLayout->addWidget(m_resetFrameBtn); controlLayout->addWidget(m_resetFrameBtn);
controlLayout->addStretch(); controlLayout->addStretch();
customLayout->addWidget(m_controlGroup); m_mainLayout->addWidget(m_controlGroup);
// 创建状态显示面板 // 创建状态显示面板
m_statusGroup = new QGroupBox("Status Information", this); m_statusGroup = new QGroupBox("Status Information", this);
QVBoxLayout *statusLayout = new QVBoxLayout(m_statusGroup); QVBoxLayout *statusLayout = new QVBoxLayout(m_statusGroup);
m_lockStatusLabel = new QLabel("Screen Lock Status: Unknown", this); m_rendererTypeLabel = new QLabel("Renderer Type: Unknown", this);
m_paintStatusLabel = new QLabel("Painting Status: Unknown", this);
m_frameCountLabel = new QLabel("Frame Count: 0", this);
m_detectorStatusLabel = new QLabel("Detector Status: Initializing...", this); m_detectorStatusLabel = new QLabel("Detector Status: Initializing...", this);
m_initStatusLabel = new QLabel("Renderer Status: Not Initialized", this);
m_lockStatusLabel = new QLabel("Screen Lock Status: Unknown", this);
m_renderStatusLabel = new QLabel("Rendering Status: Unknown", this);
m_frameCountLabel = new QLabel("Frame Count: 0", this);
m_lockStatusLabel->setFont(statusFont); m_rendererTypeLabel->setFont(statusFont);
m_paintStatusLabel->setFont(statusFont);
m_frameCountLabel->setFont(statusFont);
m_detectorStatusLabel->setFont(statusFont); m_detectorStatusLabel->setFont(statusFont);
m_initStatusLabel->setFont(statusFont);
m_lockStatusLabel->setFont(statusFont);
m_renderStatusLabel->setFont(statusFont);
m_frameCountLabel->setFont(statusFont);
statusLayout->addWidget(m_rendererTypeLabel);
statusLayout->addWidget(m_detectorStatusLabel); statusLayout->addWidget(m_detectorStatusLabel);
statusLayout->addWidget(m_initStatusLabel);
statusLayout->addWidget(m_lockStatusLabel); statusLayout->addWidget(m_lockStatusLabel);
statusLayout->addWidget(m_paintStatusLabel); statusLayout->addWidget(m_renderStatusLabel);
statusLayout->addWidget(m_frameCountLabel); statusLayout->addWidget(m_frameCountLabel);
customLayout->addWidget(m_statusGroup); m_mainLayout->addWidget(m_statusGroup);
m_tabWidget->addTab(customTab, "QPainter Widget");
} }
void MainWindow::setupConnections() void MainWindow::setupConnections()
@ -226,35 +164,23 @@ void MainWindow::setupConnections()
this, &MainWindow::onLockStateChanged); this, &MainWindow::onLockStateChanged);
// 连接按钮信号 // 连接按钮信号
connect(m_enablePaintBtn, &QPushButton::clicked, connect(m_enableRenderBtn, &QPushButton::clicked,
this, &MainWindow::onEnablePaintingClicked); this, &MainWindow::onEnableRenderingClicked);
connect(m_disablePaintBtn, &QPushButton::clicked, connect(m_disableRenderBtn, &QPushButton::clicked,
this, &MainWindow::onDisablePaintingClicked); this, &MainWindow::onDisableRenderingClicked);
connect(m_resetFrameBtn, &QPushButton::clicked, connect(m_resetFrameBtn, &QPushButton::clicked,
this, &MainWindow::onResetFrameCountClicked); this, &MainWindow::onResetFrameCountClicked);
#ifdef ENABLE_VULKAN_WIDGET
// 连接Vulkan按钮信号
connect(m_enableVulkanBtn, &QPushButton::clicked,
this, &MainWindow::onEnableVulkanClicked);
connect(m_disableVulkanBtn, &QPushButton::clicked,
this, &MainWindow::onDisableVulkanClicked);
connect(m_resetVulkanFrameBtn, &QPushButton::clicked,
this, &MainWindow::onResetVulkanFrameCountClicked);
#endif // ENABLE_VULKAN_WIDGET
} }
void MainWindow::onScreenLocked() void MainWindow::onScreenLocked()
{ {
qDebug() << "MainWindow: Screen locked event received"; qDebug() << "MainWindow: Screen locked event received";
// 停止绘制 // 停止渲染
if (m_customWidget) { if (m_renderWidget) {
m_customWidget->setPaintingEnabled(false); m_renderWidget->setRenderingEnabled(false);
} }
updateStatusDisplay(); updateStatusDisplay();
@ -265,9 +191,9 @@ void MainWindow::onScreenUnlocked()
{ {
qDebug() << "MainWindow: Screen unlocked event received"; qDebug() << "MainWindow: Screen unlocked event received";
// 恢复绘制 // 恢复渲染
if (m_customWidget) { if (m_renderWidget) {
m_customWidget->setPaintingEnabled(true); m_renderWidget->setRenderingEnabled(true);
} }
updateStatusDisplay(); updateStatusDisplay();
@ -278,9 +204,9 @@ void MainWindow::onLockStateChanged(bool locked)
{ {
qDebug() << "MainWindow: Lock state changed to:" << (locked ? "LOCKED" : "UNLOCKED"); qDebug() << "MainWindow: Lock state changed to:" << (locked ? "LOCKED" : "UNLOCKED");
// 根据锁屏状态自动启用/禁用绘制 // 根据锁屏状态自动启用/禁用渲染
if (m_customWidget) { if (m_renderWidget) {
m_customWidget->setPaintingEnabled(!locked); m_renderWidget->setRenderingEnabled(!locked);
} }
updateStatusDisplay(); updateStatusDisplay();
@ -289,10 +215,14 @@ void MainWindow::onLockStateChanged(bool locked)
void MainWindow::updateStatusDisplay() void MainWindow::updateStatusDisplay()
{ {
if (!m_lockDetector) { if (!m_lockDetector || !m_renderWidget) {
return; return;
} }
// 更新渲染器类型
QString rendererType = "Renderer Type: <b>" + m_renderWidget->getRendererType() + "</b>";
m_rendererTypeLabel->setText(rendererType);
// 更新检测器状态 // 更新检测器状态
QString detectorStatus = "Detector Status: "; QString detectorStatus = "Detector Status: ";
if (m_lockDetector) { if (m_lockDetector) {
@ -302,6 +232,19 @@ void MainWindow::updateStatusDisplay()
} }
m_detectorStatusLabel->setText(detectorStatus); m_detectorStatusLabel->setText(detectorStatus);
// 更新初始化状态
QString initStatus = "Renderer Status: ";
if (m_renderWidget->isInitialized()) {
initStatus += "<span style='color: green;'><b>✓ Initialized</b></span>";
} else {
initStatus += "<span style='color: orange;'><b>⚠ Not Initialized</b></span>";
QString error = m_renderWidget->getLastError();
if (!error.isEmpty()) {
initStatus += " - " + error;
}
}
m_initStatusLabel->setText(initStatus);
// 更新锁屏状态 // 更新锁屏状态
bool isLocked = m_lockDetector->isScreenLocked(); bool isLocked = m_lockDetector->isScreenLocked();
QString lockStatus = "Screen Lock Status: "; QString lockStatus = "Screen Lock Status: ";
@ -312,84 +255,63 @@ void MainWindow::updateStatusDisplay()
} }
m_lockStatusLabel->setText(lockStatus); m_lockStatusLabel->setText(lockStatus);
// 更新绘制状态 // 更新渲染状态
bool isPainting = m_customWidget ? m_customWidget->isPaintingEnabled() : false; bool isRendering = m_renderWidget->isRenderingEnabled();
QString paintStatus = "Painting Status: "; QString renderStatus = "Rendering Status: ";
if (isPainting) { if (isRendering) {
paintStatus += "<span style='color: green;'><b>✓ ENABLED (Active)</b></span>"; renderStatus += "<span style='color: green;'><b>✓ ENABLED (Active)</b></span>";
} else { } else {
paintStatus += "<span style='color: red;'><b>✗ DISABLED (Stopped)</b></span>"; renderStatus += "<span style='color: red;'><b>✗ DISABLED (Stopped)</b></span>";
} }
m_paintStatusLabel->setText(paintStatus); m_renderStatusLabel->setText(renderStatus);
// 更新帧计数 // 更新帧计数
int frameCount = m_customWidget ? m_customWidget->getPaintFrameCount() : 0; int frameCount = m_renderWidget->getRenderFrameCount();
QString frameCountStr = QString("Frame Count: <b>%1</b> frames").arg(frameCount); QString frameCountStr = QString("Frame Count: <b>%1</b> frames").arg(frameCount);
m_frameCountLabel->setText(frameCountStr); m_frameCountLabel->setText(frameCountStr);
#ifdef ENABLE_VULKAN_WIDGET
// 更新Vulkan状态
if (m_vulkanWidget) {
// 更新初始化状态
QString vulkanInitStatus = "Vulkan Status: ";
if (m_vulkanWidget->isInitialized()) {
vulkanInitStatus += "<span style='color: green;'><b>✓ Initialized</b></span>";
} else {
vulkanInitStatus += "<span style='color: orange;'><b>⚠ Not Initialized</b></span>";
if (!m_vulkanWidget->getLastError().isEmpty()) {
vulkanInitStatus += " - " + m_vulkanWidget->getLastError();
}
}
m_vulkanInitLabel->setText(vulkanInitStatus);
// 更新渲染状态
bool isVulkanRendering = m_vulkanWidget->isRenderingEnabled();
QString vulkanRenderStatus = "Rendering Status: ";
if (isVulkanRendering) {
vulkanRenderStatus += "<span style='color: green;'><b>✓ ENABLED (Active)</b></span>";
} else {
vulkanRenderStatus += "<span style='color: red;'><b>✗ DISABLED (Stopped)</b></span>";
}
m_vulkanRenderStatusLabel->setText(vulkanRenderStatus);
// 更新Vulkan帧计数
int vulkanFrameCount = m_vulkanWidget->getRenderFrameCount();
QString vulkanFrameCountStr = QString("Frame Count: <b>%1</b> frames").arg(vulkanFrameCount);
m_vulkanFrameCountLabel->setText(vulkanFrameCountStr);
// 更新Vulkan按钮状态
m_enableVulkanBtn->setEnabled(!isVulkanRendering && m_vulkanWidget->isInitialized());
m_disableVulkanBtn->setEnabled(isVulkanRendering);
}
#endif // ENABLE_VULKAN_WIDGET
} }
void MainWindow::updateButtonStates() void MainWindow::updateButtonStates()
{ {
// 根据当前绘制状态更新按钮可用性 if (!m_renderWidget) {
bool isPainting = m_customWidget ? m_customWidget->isPaintingEnabled() : false; return;
m_enablePaintBtn->setEnabled(!isPainting); }
m_disablePaintBtn->setEnabled(isPainting);
// 根据当前渲染状态更新按钮可用性
bool isRendering = m_renderWidget->isRenderingEnabled();
bool isInitialized = m_renderWidget->isInitialized();
m_enableRenderBtn->setEnabled(!isRendering && isInitialized);
m_disableRenderBtn->setEnabled(isRendering);
} }
void MainWindow::onEnablePaintingClicked() void MainWindow::onEnableRenderingClicked()
{ {
qDebug() << "Manual enable painting clicked"; qDebug() << "Manual enable rendering clicked";
if (m_customWidget) { if (m_renderWidget) {
m_customWidget->setPaintingEnabled(true); if (!m_renderWidget->isInitialized()) {
bool success = m_renderWidget->initializeRenderer();
if (!success) {
QMessageBox::warning(this, "Renderer Initialization Failed",
"Failed to initialize renderer:\n" + m_renderWidget->getLastError());
updateStatusDisplay();
return;
}
}
m_renderWidget->setRenderingEnabled(true);
} }
updateStatusDisplay(); updateStatusDisplay();
updateButtonStates(); updateButtonStates();
} }
void MainWindow::onDisablePaintingClicked() void MainWindow::onDisableRenderingClicked()
{ {
qDebug() << "Manual disable painting clicked"; qDebug() << "Manual disable rendering clicked";
if (m_customWidget) { if (m_renderWidget) {
m_customWidget->setPaintingEnabled(false); m_renderWidget->setRenderingEnabled(false);
} }
updateStatusDisplay(); updateStatusDisplay();
@ -400,53 +322,9 @@ void MainWindow::onResetFrameCountClicked()
{ {
qDebug() << "Reset frame count clicked"; qDebug() << "Reset frame count clicked";
if (m_customWidget) { if (m_renderWidget) {
m_customWidget->resetFrameCount(); m_renderWidget->resetFrameCount();
} }
updateStatusDisplay(); updateStatusDisplay();
} }
#ifdef ENABLE_VULKAN_WIDGET
void MainWindow::onEnableVulkanClicked()
{
qDebug() << "Manual enable Vulkan rendering clicked";
if (m_vulkanWidget) {
if (!m_vulkanWidget->isInitialized()) {
bool success = m_vulkanWidget->initializeVulkan();
if (!success) {
QMessageBox::warning(this, "Vulkan Initialization Failed",
"Failed to initialize Vulkan:\n" + m_vulkanWidget->getLastError());
updateStatusDisplay();
return;
}
}
m_vulkanWidget->setRenderingEnabled(true);
}
updateStatusDisplay();
}
void MainWindow::onDisableVulkanClicked()
{
qDebug() << "Manual disable Vulkan rendering clicked";
if (m_vulkanWidget) {
m_vulkanWidget->setRenderingEnabled(false);
}
updateStatusDisplay();
}
void MainWindow::onResetVulkanFrameCountClicked()
{
qDebug() << "Reset Vulkan frame count clicked";
if (m_vulkanWidget) {
m_vulkanWidget->resetFrameCount();
}
updateStatusDisplay();
}
#endif // ENABLE_VULKAN_WIDGET

View File

@ -8,17 +8,14 @@
#include <QLabel> #include <QLabel>
#include <QGroupBox> #include <QGroupBox>
#include <QTimer> #include <QTimer>
#include <QTabWidget>
#include "screenlockdetector.h" #include "screenlockdetector.h"
#include "customwidget.h" #include "renderwidgetbase.h"
#ifdef ENABLE_VULKAN_WIDGET
#include "vulkanwidget.h"
#endif
/** /**
* @brief * @brief
* *
* *
* 使RenderWidgetBase基类指针Vulkan或QPainter实现
*/ */
class MainWindow : public QMainWindow class MainWindow : public QMainWindow
{ {
@ -51,37 +48,20 @@ private slots:
void updateStatusDisplay(); void updateStatusDisplay();
/** /**
* @brief * @brief
*/ */
void onEnablePaintingClicked(); void onEnableRenderingClicked();
/** /**
* @brief * @brief
*/ */
void onDisablePaintingClicked(); void onDisableRenderingClicked();
/** /**
* @brief * @brief
*/ */
void onResetFrameCountClicked(); void onResetFrameCountClicked();
#ifdef ENABLE_VULKAN_WIDGET
/**
* @brief Vulkan渲染按钮点击
*/
void onEnableVulkanClicked();
/**
* @brief Vulkan渲染按钮点击
*/
void onDisableVulkanClicked();
/**
* @brief Vulkan帧计数按钮点击
*/
void onResetVulkanFrameCountClicked();
#endif
private: private:
/** /**
* @brief UI组件 * @brief UI组件
@ -101,42 +81,26 @@ private:
private: private:
// 核心组件 // 核心组件
ScreenLockDetector *m_lockDetector; ScreenLockDetector *m_lockDetector;
CustomWidget *m_customWidget; RenderWidgetBase *m_renderWidget; // 统一的渲染组件指针
#ifdef ENABLE_VULKAN_WIDGET
VulkanWidget *m_vulkanWidget;
#endif
// UI组件 // UI组件
QWidget *m_centralWidget; QWidget *m_centralWidget;
QVBoxLayout *m_mainLayout; QVBoxLayout *m_mainLayout;
QTabWidget *m_tabWidget;
// 控制面板 - CustomWidget // 控制面板
QGroupBox *m_controlGroup; QGroupBox *m_controlGroup;
QPushButton *m_enablePaintBtn; QPushButton *m_enableRenderBtn;
QPushButton *m_disablePaintBtn; QPushButton *m_disableRenderBtn;
QPushButton *m_resetFrameBtn; QPushButton *m_resetFrameBtn;
#ifdef ENABLE_VULKAN_WIDGET
// 控制面板 - VulkanWidget
QGroupBox *m_vulkanControlGroup;
QPushButton *m_enableVulkanBtn;
QPushButton *m_disableVulkanBtn;
QPushButton *m_resetVulkanFrameBtn;
#endif
// 状态显示 - CustomWidget // 状态显示
QGroupBox *m_statusGroup; QGroupBox *m_statusGroup;
QLabel *m_rendererTypeLabel;
QLabel *m_lockStatusLabel; QLabel *m_lockStatusLabel;
QLabel *m_paintStatusLabel; QLabel *m_renderStatusLabel;
QLabel *m_frameCountLabel; QLabel *m_frameCountLabel;
QLabel *m_detectorStatusLabel; QLabel *m_detectorStatusLabel;
#ifdef ENABLE_VULKAN_WIDGET QLabel *m_initStatusLabel;
// 状态显示 - VulkanWidget
QGroupBox *m_vulkanStatusGroup;
QLabel *m_vulkanInitLabel;
QLabel *m_vulkanRenderStatusLabel;
QLabel *m_vulkanFrameCountLabel;
#endif
// 更新定时器 // 更新定时器
QTimer *m_updateTimer; QTimer *m_updateTimer;

73
src/renderwidgetbase.h Normal file
View File

@ -0,0 +1,73 @@
#ifndef RENDERWIDGETBASE_H
#define RENDERWIDGETBASE_H
#include <QWidget>
#include <QString>
/**
* @brief
*
* VulkanWidget和CustomWidget提供统一的接口
* MainWindow使用此基类指针来操作不同的渲染实现
*/
class RenderWidgetBase : public QWidget
{
Q_OBJECT
public:
explicit RenderWidgetBase(QWidget *parent = nullptr)
: QWidget(parent)
{
}
virtual ~RenderWidgetBase() = default;
/**
* @brief Vulkan需要QPainter不需要
* @return true表示初始化成功false表示失败
*/
virtual bool initializeRenderer() = 0;
/**
* @brief /
* @param enabled true表示启用false表示禁用
*/
virtual void setRenderingEnabled(bool enabled) = 0;
/**
* @brief /
* @return true表示已启用false表示已禁用
*/
virtual bool isRenderingEnabled() const = 0;
/**
* @brief /
* @return
*/
virtual int getRenderFrameCount() const = 0;
/**
* @brief
*/
virtual void resetFrameCount() = 0;
/**
* @brief
* @return true表示渲染器已成功初始化
*/
virtual bool isInitialized() const = 0;
/**
* @brief
* @return
*/
virtual QString getLastError() const = 0;
/**
* @brief
* @return "Vulkan""QPainter"
*/
virtual QString getRendererType() const = 0;
};
#endif // RENDERWIDGETBASE_H

View File

@ -26,7 +26,7 @@
#endif #endif
VulkanWidget::VulkanWidget(QWidget *parent) VulkanWidget::VulkanWidget(QWidget *parent)
: QWidget(parent) : RenderWidgetBase(parent)
, m_instance(VK_NULL_HANDLE) , m_instance(VK_NULL_HANDLE)
, m_physicalDevice(VK_NULL_HANDLE) , m_physicalDevice(VK_NULL_HANDLE)
, m_device(VK_NULL_HANDLE) , m_device(VK_NULL_HANDLE)
@ -85,6 +85,76 @@ VulkanWidget::~VulkanWidget()
qDebug() << "VulkanWidget destroyed"; qDebug() << "VulkanWidget destroyed";
} }
// 实现 RenderWidgetBase 接口
bool VulkanWidget::initializeRenderer()
{
return initializeVulkan();
}
void VulkanWidget::setRenderingEnabled(bool enabled)
{
if (m_renderingEnabled == enabled) {
return;
}
m_renderingEnabled = enabled;
if (m_renderingEnabled) {
qDebug() << "Vulkan rendering ENABLED - Resuming animations";
// 恢复渲染时,重新启动定时器(锁屏时已停止)
if (!m_renderTimer->isActive()) {
m_renderTimer->start(16); // ~60 FPS
qDebug() << "Render timer restarted";
}
// Unlocked: calculate lock duration
if (m_lastLockTime.isValid()) {
QDateTime unlockTime = QDateTime::currentDateTime();
m_lastLockDuration = m_lastLockTime.secsTo(unlockTime);
m_lockPaintFrameCount = m_frameCount - m_lastLockFrameCount;
qDebug() << "Screen was locked for" << m_lastLockDuration << "seconds";
qDebug() << "Frames at lock:" << m_lastLockFrameCount
<< "- Frames painted during lock:" << m_lockPaintFrameCount;
}
m_startTime = QDateTime::currentDateTime();
} else {
qDebug() << "Vulkan rendering DISABLED - Showing locked state";
// 关键修复:渲染一帧锁屏界面后停止定时器
m_needsLockedFrameUpdate = true; // 标记需要渲染锁屏帧
// Locked: record lock time
m_pauseTime = QDateTime::currentDateTime();
m_lastLockTime = m_pauseTime;
m_lastLockFrameCount = m_frameCount;
m_lockCount++;
qDebug() << "Screen locked at" << m_lastLockTime.toString("yyyy-MM-dd hh:mm:ss")
<< "- Lock count:" << m_lockCount
<< "- Frame count at lock:" << m_lastLockFrameCount;
}
}
bool VulkanWidget::isRenderingEnabled() const
{
return m_renderingEnabled;
}
int VulkanWidget::getRenderFrameCount() const
{
return m_frameCount;
}
void VulkanWidget::resetFrameCount()
{
m_frameCount = 0;
qDebug() << "Vulkan frame count reset";
}
QString VulkanWidget::getRendererType() const
{
return QString("Vulkan");
}
bool VulkanWidget::initializeVulkan() bool VulkanWidget::initializeVulkan()
{ {
qDebug() << "Initializing Vulkan..."; qDebug() << "Initializing Vulkan...";
@ -906,64 +976,7 @@ void VulkanWidget::cleanupVulkan()
qDebug() << "Vulkan cleanup complete"; qDebug() << "Vulkan cleanup complete";
} }
void VulkanWidget::setRenderingEnabled(bool enabled)
{
if (m_renderingEnabled == enabled) {
return;
}
m_renderingEnabled = enabled;
if (m_renderingEnabled) {
qDebug() << "Vulkan rendering ENABLED - Resuming animations";
// 恢复渲染时,重新启动定时器(锁屏时已停止)
if (!m_renderTimer->isActive()) {
m_renderTimer->start(16); // ~60 FPS
qDebug() << "Render timer restarted";
}
// Unlocked: calculate lock duration
if (m_lastLockTime.isValid()) {
QDateTime unlockTime = QDateTime::currentDateTime();
m_lastLockDuration = m_lastLockTime.secsTo(unlockTime);
m_lockPaintFrameCount = m_frameCount - m_lastLockFrameCount;
qDebug() << "Screen was locked for" << m_lastLockDuration << "seconds";
qDebug() << "Frames at lock:" << m_lastLockFrameCount
<< "- Frames painted during lock:" << m_lockPaintFrameCount;
}
m_startTime = QDateTime::currentDateTime();
} else {
qDebug() << "Vulkan rendering DISABLED - Showing locked state";
// 关键修复:渲染一帧锁屏界面后停止定时器
m_needsLockedFrameUpdate = true; // 标记需要渲染锁屏帧
// Locked: record lock time
m_pauseTime = QDateTime::currentDateTime();
m_lastLockTime = m_pauseTime;
m_lastLockFrameCount = m_frameCount;
m_lockCount++;
qDebug() << "Screen locked at" << m_lastLockTime.toString("yyyy-MM-dd hh:mm:ss")
<< "- Lock count:" << m_lockCount
<< "- Frame count at lock:" << m_lastLockFrameCount;
}
}
bool VulkanWidget::isRenderingEnabled() const
{
return m_renderingEnabled;
}
int VulkanWidget::getRenderFrameCount() const
{
return m_frameCount;
}
void VulkanWidget::resetFrameCount()
{
m_frameCount = 0;
qDebug() << "Frame count reset";
}
void VulkanWidget::showEvent(QShowEvent *event) void VulkanWidget::showEvent(QShowEvent *event)
{ {

View File

@ -1,7 +1,7 @@
#ifndef VULKANWIDGET_H #ifndef VULKANWIDGET_H
#define VULKANWIDGET_H #define VULKANWIDGET_H
#include <QWidget> #include "renderwidgetbase.h"
#include <QString> #include <QString>
#include <QTimer> #include <QTimer>
#include <QDateTime> #include <QDateTime>
@ -30,55 +30,27 @@ typedef VkFlags VkSurfaceTransformFlagsKHR;
* 使Qt的native window属性创建Vulkan Surface * 使Qt的native window属性创建Vulkan Surface
* volk机制加载Vulkan函数 * volk机制加载Vulkan函数
*/ */
class VulkanWidget : public QWidget class VulkanWidget : public RenderWidgetBase
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit VulkanWidget(QWidget *parent = nullptr); explicit VulkanWidget(QWidget *parent = nullptr);
~VulkanWidget(); ~VulkanWidget() override;
/** // 实现RenderWidgetBase接口
* @brief Vulkan环境 bool initializeRenderer() override;
* @return true表示初始化成功false表示失败 void setRenderingEnabled(bool enabled) override;
*/ bool isRenderingEnabled() const override;
int getRenderFrameCount() const override;
void resetFrameCount() override;
bool isInitialized() const override { return m_initialized; }
QString getLastError() const override { return m_lastError; }
QString getRendererType() const override;
// VulkanWidget特有的方法保持兼容性
bool initializeVulkan(); bool initializeVulkan();
/**
* @brief
* @param enabled true表示启用渲染false表示禁用
*/
void setRenderingEnabled(bool enabled);
/**
* @brief
* @return true表示渲染已启用false表示已禁用
*/
bool isRenderingEnabled() const;
/**
* @brief
* @return
*/
int getRenderFrameCount() const;
/**
* @brief
*/
void resetFrameCount();
/**
* @brief
* @return true表示Vulkan已成功初始化
*/
bool isInitialized() const { return m_initialized; }
/**
* @brief
* @return
*/
QString getLastError() const { return m_lastError; }
protected: protected:
/** /**
* @brief Qt事件 * @brief Qt事件