鱼C论坛

 找回密码
 立即注册
查看: 127|回复: 3

[技术交流] 如何让ScreenConfig在不继承pyside6的任何类的情况下,报错AttributeError

[复制链接]
发表于 2025-8-15 11:07:37 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
class ScreenConfig:
    """一次性计算所有屏幕参数"""

    def __init__(self):
        screen = QGuiApplication.primaryScreen().geometry()
        self.screen_width = screen.width()
        self.screen_height = screen.height()

        # 计算常用参数(按需扩展)
        self.font_size = self.screen_height * 0.015
        self.header_height = self.screen_height * 0.1
        self.window_margin = self.screen_width * 0.02


# 全局单例(确保QApplication已初始化后创建)
screen_config = ScreenConfig()
以上代码报错:
    screen = QGuiApplication.primaryScreen().geometry()
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'geometry'
如何让ScreenConfig在不继承pyside6的任何类的情况下,报错AttributeError,并可以正确计算各项参数
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2025-8-15 11:10:15 | 显示全部楼层
要使 `ScreenConfig` 在不继承 PySide6 类的情况下正确运行,需要解决 `QGuiApplication` 未初始化的问题。以下是修改方案:

### 修改后的代码(惰性初始化 + 延迟计算):

  1. class ScreenConfig:
  2.     """一次性计算所有屏幕参数(惰性初始化)"""
  3.    
  4.     def __init__(self):
  5.         self._initialized = False  # 初始化状态标记
  6.    
  7.     def _initialize(self):
  8.         """实际执行参数计算的私有方法"""
  9.         screen = QGuiApplication.primaryScreen().geometry()
  10.         self.screen_width = screen.width()
  11.         self.screen_height = screen.height()
  12.         self.font_size = self.screen_height * 0.015
  13.         self.header_height = self.screen_height * 0.1
  14.         self.window_margin = self.screen_width * 0.02
  15.         self._initialized = True
  16.    
  17.     def __getattr__(self, name):
  18.         """在访问属性时按需初始化"""
  19.         if not self._initialized:
  20.             self._initialize()
  21.         return self.__dict__[name]  # 返回已计算的属性值

  22. # 全局单例(此时不立即计算参数)
  23. screen_config = ScreenConfig()
复制代码


### 关键修改说明:
1. **惰性初始化**:
   - 在 `__init__` 中只设置初始化标记 self._initialized=False
   - 首次访问属性时通过 __getattr__ 触发实际计算

2. **错误处理逻辑**:
   - 若在创建 QApplication 前访问属性:
   
  1. # 错误示例(QApplication未初始化)
  2.      print(screen_config.screen_width)
复制代码

     **触发原版报错**:
   
  1. AttributeError: 'NoneType' object has no attribute 'geometry'
复制代码


3. **正确使用方式**:
  
  1. from PySide6.QtWidgets import QApplication
  2.    import sys
  3.    
  4.    app = QApplication(sys.argv)  # 先初始化QApplication
  5.    
  6.    # 此时访问属性会正常计算
  7.    print(screen_config.screen_width)  # 输出屏幕宽度
复制代码


### 注意事项:
1. **错误触发条件**:必须确保在访问属性前已创建 QApplication 实例
2. **单例优势**:全局对象 screen_config 只需初始化一次
3. **线程安全**:该方案适用于主线程,多线程场景需额外同步

> 通过此设计,既保留了原错误触发机制(确保调试时能发现问题),又能在正确初始化后自动计算参数。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-8-15 11:24:17 | 显示全部楼层
我每次在其他py文件中访问self.font_size时__getattr__方法都会调用一次对吗?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-8-15 11:25:57 | 显示全部楼层
rxts 发表于 2025-08-15 11:24
我每次在其他py文件中访问self.font_size时__getattr_ ...


您的问题很好理解。在您提供的 `ScreenConfig` 类中,使用 `__getattr__` 方法时,**不会每次访问 `self.font_size` 都触发 `__getattr__` 方法**。具体行为如下:

### 属性访问机制:
1. **首次访问任何属性时**:
   - 会触发 `__getattr__` 方法
   - 执行 `_initialize()` 完成参数计算
   - 设置 `self._initialized = True`

2. **后续访问已存在的属性时**:
   - 如 `self.font_size`、`self.screen_width` 等
   - **不会触发** `__getattr__` 方法
   - 直接从实例字典中获取值

### 验证示例:
class ScreenConfig:
    def __init__(self):
        self._initialized = False
   
    def _initialize(self):
        print("执行初始化计算!")  # 添加打印以便观察
        # 实际计算代码...
        self.font_size = 16  # 示例值
        self._initialized = True
   
    def __getattr__(self, name):
        if not self._initialized:
            self._initialize()
        return getattr(self, name)  # 返回已存在的属性

# 测试
config = ScreenConfig()
print("第一次访问:", config.font_size)  # 触发初始化
print("第二次访问:", config.font_size)  # 直接返回值
print("第三次访问:", config.font_size)  # 直接返回值

### 输出结果:
执行初始化计算!
第一次访问: 16
第二次访问: 16
第三次访问: 16

### 关键结论:
1. `__getattr__` 仅在**属性不存在时**被调用
2. 初始化完成后,所有属性已存在于实例中
3. 后续访问直接从 `self.__dict__` 读取属性值
4. 访问已存在的属性与普通类属性访问效率相同

> 因此您无需担心性能问题,后续访问 `screen_config.font_size` 的效率与访问普通类属性完全一致,不会反复触发初始化逻辑。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-9-4 02:03

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表