Skip to content

Commit 808c9ed

Browse files
committed
Update qrc-rcc
1 parent a7ad0e6 commit 808c9ed

File tree

2 files changed

+211
-19
lines changed

2 files changed

+211
-19
lines changed

07-Packaging-资源管理与打包/01-资源管理/01-在PyQt中使用qrc-rcc资源系统.md

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -118,48 +118,48 @@ Qt Resource Compiler version 6.4.1
118118

119119
Options:
120120
-h, --help 显示关于命令行选项的帮助
121-
121+
122122
--help-all 显示包括Qt独有选项在内的所有帮助
123-
123+
124124
-v, --version 显示版本信息
125-
125+
126126
-o, --output <file> 将输出写入到 <file> 中,而不是 stdout 中
127127

128128
-t, --temp <file> 为大资源文件使用临时文件 <file>
129-
129+
130130
--name <name><name> 创建一个外部初始化函数
131-
131+
132132
--root <path> 用根目录 <path> 作为资源访问路径的前缀
133-
133+
134134
--compress-algo <algo> 使用 <algo> 算法压缩输入文件([zlib], none)
135-
135+
136136
--compress <level><level> 级别压缩输入文件
137-
137+
138138
--no-compress 禁用所有压缩,等同于 --compress-algo=none
139-
139+
140140
--no-zstd 禁止使用 zstd 压缩
141-
141+
142142
--threshold <level> 衡量是否值得进行压缩的阈值
143-
143+
144144
--binary 输出一个作为动态资源使用的二进制文件
145-
145+
146146
-g, --generator <cpp|python|python2> 选择生成器
147-
147+
148148
--pass <number> Pass number for big resources
149-
149+
150150
--namespace 关闭命名空间宏
151-
151+
152152
--verbose 启用 verbose 模式
153-
153+
154154
--list 只列出 .qrc 文件条目,不生成代码
155-
155+
156156
--list-mapping 只输出 .qrc 中定义的资源路径与文件系统路径的
157157
映射,不生成代码
158-
158+
159159
-d, --depfile <file><file> 中写入一个包含 .qrc 依赖项的 depfile
160160

161161
--project 输出一个包含当前目录下所有文件的资源文件
162-
162+
163163
--format-version <number> 写入 RCC 格式的版本
164164

165165
Arguments:
@@ -302,6 +302,15 @@ def get_about_text():
302302
return about_text
303303
```
304304

305+
或者使用本项目提供的 [`OpenQFile`](./open_qfile.py)
306+
307+
```python
308+
from open_qfile import OpenQFile
309+
310+
with OpenQFile(":/texts/About_Text", "rt", encoding="utf-8") as f:
311+
about_text = f.read()
312+
```
313+
305314
对于图片,可以在创建 [QIcon](https://doc.qt.io/qt-6/qicon.html)[QImage](https://doc.qt.io/qt-6/qimage.html)[QPixmap](https://doc.qt.io/qt-6/qpixmap.html) 对象时将直接资源路径作为参数传入:
306315

307316
```python
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
import locale
2+
import os
3+
import warnings
4+
from typing import Optional, Union
5+
6+
from PySide6.QtCore import QFile, QIODevice
7+
8+
9+
class OpenQFile:
10+
"""
11+
用于以QFile形式打开文件的上下文管理器 \n
12+
使支持 Python 的 with 风格 \n
13+
"""
14+
15+
def __init__(self, file: Union[str, bytes, os.PathLike[str]],
16+
mode="r",
17+
encoding: Optional[str] = None):
18+
"""
19+
:param file: 文件路径
20+
:param mode: 打开模式(暂时只支持文本读取)
21+
:param encoding: 文本文件编码
22+
"""
23+
24+
# 分析模式是否合法、返回正确的 FileIo 类实例
25+
# https://docs.python.org/zh-cn/3/library/functions.html#open
26+
if "b" not in mode:
27+
# 文本模式
28+
self.io_obj = PyQTextFileIo(file, mode, encoding)
29+
else:
30+
# 二进制模式(暂不支持)
31+
# self.io_obj = PyQByteFileIo(file, mode)
32+
raise ValueError("暂不支持该模式")
33+
34+
def __enter__(self):
35+
return self.io_obj
36+
37+
def __exit__(self, exc_type, exc_val, exc_tb):
38+
self.io_obj.close()
39+
40+
41+
class PyQTextFileIo:
42+
"""
43+
将 QFile 中处理文本文件读写的部分封装成 Python的 io 风格
44+
目前只支持读取,不支持写入
45+
"""
46+
47+
@classmethod
48+
def _parse_mode(cls, py_mode: str) -> QIODevice:
49+
"""
50+
解析文件打开模式,将 Python open() 风格转换至 QIODevice.OpenModeFlag
51+
https://docs.python.org/zh-cn/3/library/functions.html#open
52+
https://doc.qt.io/qt-6/qiodevicebase.html#OpenModeFlag-enum
53+
:return: mode
54+
"""
55+
56+
qt_mode: QIODevice = QIODevice.Text
57+
58+
# 暂不支持写入
59+
if "r" in py_mode and "+" not in py_mode:
60+
qt_mode = qt_mode | QIODevice.ReadOnly
61+
elif "w" in py_mode:
62+
qt_mode = qt_mode | QIODevice.WriteOnly
63+
elif "+" in py_mode:
64+
qt_mode = qt_mode | QIODevice.ReadWrite
65+
66+
if "x" in py_mode:
67+
qt_mode = qt_mode | QIODevice.NewOnly
68+
69+
return qt_mode
70+
71+
def __init__(self, file: Union[str, bytes, os.PathLike[str]],
72+
mode,
73+
encoding: Optional[str] = None):
74+
75+
self._file = QFile(file) # TODO 处理 QFile 只接受`/`风格路径可能导致 Windows 平台异常的问题
76+
77+
if encoding is not None:
78+
self.encoding = encoding
79+
else:
80+
# 用户未指定编码,则使用当前平台默认编码
81+
self.encoding = locale.getencoding()
82+
83+
self.mode = self._parse_mode(mode)
84+
self._file.open(self.mode)
85+
86+
def readable(self) -> bool:
87+
"""
88+
当前文件是否可读 \n
89+
:return: isReadable
90+
"""
91+
return self._file.isReadable()
92+
93+
def read(self, size: int = -1) -> str:
94+
"""
95+
从流中读取至多 size 个字符并以单个 str 的形式返回。 如果 size 为负值或 None,则读取至 EOF。 \n
96+
https://docs.python.org/3/library/io.html#io.TextIOBase.read
97+
:param size: 读取的字符数,负值或 None 表示一直读取直到 EOF
98+
:return: 文件中读出的文本内容
99+
"""
100+
101+
if not self.readable():
102+
raise OSError(f"File '{self._file.fileName()}' is not Readable.")
103+
104+
if size < 0 or size is None:
105+
# 读取文件,并将 QByteArray 转为 str
106+
text = str(self._file.readAll(), encoding=self.encoding)
107+
else:
108+
# 已知问题:性能太差
109+
# PySide6.QtCore.QIODevice.read(maxlen) 以字节而非字符方式计算长度,行为不一致
110+
# 而 QTextStream 对字符编码支持太差,许多编码并不支持
111+
text = str(self._file.readAll(), encoding=self.encoding)[0:size] # 性能太差
112+
113+
return text
114+
115+
def readline(self, size: int = - 1, /) -> str:
116+
"""
117+
模仿 io.TextIOBase.readline 的行为,读取文件中的一行。 \n
118+
https://docs.python.org/3/library/io.html#io.TextIOBase.readline
119+
:param size: 如果指定了 size ,最多将读取 size 个字符。
120+
:return: 单行文本
121+
"""
122+
123+
if not self.readable():
124+
raise OSError(f"File '{self._file.fileName()}' is not Readable.")
125+
126+
if self._file.atEnd():
127+
warnings.warn(f"Trying to read a line at the end of the file '{self._file.fileName()}'.")
128+
return ""
129+
else:
130+
if size == 0:
131+
return ""
132+
else:
133+
line = str(self._file.readLine(), encoding=self.encoding)
134+
if size < 0:
135+
return line
136+
else:
137+
return line[0:size]
138+
139+
def readlines(self, hint: int = -1, /) -> list[str]:
140+
"""
141+
模仿 Python 中 io.IOBase.readlines() 的行为,返回由所有行组成的字符串列表。 \n
142+
Known issue: slower than `readline()` \n
143+
https://docs.python.org/3/library/io.html#io.IOBase.readlines
144+
:param hint: 要读取的字符数
145+
:return: 文本内容所有行组成的列表
146+
"""
147+
148+
if not self.readable():
149+
raise OSError(f"File '{self._file.fileName()}' is not Readable.")
150+
151+
if hint <= 0 or hint is None:
152+
temp = str(self._file.readAll(), encoding=self.encoding)
153+
all_lines = temp.splitlines(keepends=True)
154+
else:
155+
all_lines = []
156+
char_num = 0
157+
while char_num <= hint and not self._file.atEnd():
158+
new_line = self.readline()
159+
all_lines.append(new_line)
160+
char_num += len(new_line)
161+
162+
return all_lines
163+
164+
def close(self):
165+
self._file.close()
166+
167+
168+
if __name__ == "__main__":
169+
with OpenQFile(b"./test.txt", "rt", encoding="gbk") as f:
170+
print(f.read(11))
171+
# print(f.readline())
172+
# lines = f.readlines()
173+
# print(lines)
174+
175+
print("-----------")
176+
177+
with open("./test.txt", "rt", encoding="gbk") as f:
178+
print(f.read(11))
179+
# print(f.readline())
180+
# lines = f.readlines()
181+
# print(lines)
182+
183+
# f.read() # 离开 with 语句块后文件已经被关闭,无法再读

0 commit comments

Comments
 (0)