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:
parent
8ee653e1a6
commit
2c7119d190
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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!
|
||||||
|
|
@ -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()` 始终返回 true(QPainter 不需要初始化)
|
||||||
|
- `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. ✅ 用户体验:提供了更简洁的界面
|
||||||
|
|
||||||
|
这个设计为项目的后续发展提供了坚实的基础,使得添加新功能和维护现有代码变得更加容易。
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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事件:组件显示时
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue