Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
k54kdk
PyQt Fluent Widgets
提交
019b6612
P
PyQt Fluent Widgets
项目概览
k54kdk
/
PyQt Fluent Widgets
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
PyQt Fluent Widgets
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
019b6612
编写于
4月 07, 2023
作者:
之一Yo
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
添加可编辑下拉框 `EditableComboBox`
上级
b43aff7c
变更
24
展开全部
隐藏空白更改
内联
并排
Showing
24 changed file
with
34499 addition
and
34315 deletion
+34499
-34315
examples/combo_box/demo.py
examples/combo_box/demo.py
+2
-2
examples/gallery/app/resource/i18n/gallery_hk.qm
examples/gallery/app/resource/i18n/gallery_hk.qm
+0
-0
examples/gallery/app/resource/i18n/gallery_hk.ts
examples/gallery/app/resource/i18n/gallery_hk.ts
+68
-48
examples/gallery/app/resource/i18n/gallery_zh.qm
examples/gallery/app/resource/i18n/gallery_zh.qm
+0
-0
examples/gallery/app/resource/i18n/gallery_zh.ts
examples/gallery/app/resource/i18n/gallery_zh.ts
+40
-20
examples/gallery/app/view/basic_input_interface.py
examples/gallery/app/view/basic_input_interface.py
+17
-1
examples/gallery/app/view/text_interface.py
examples/gallery/app/view/text_interface.py
+2
-1
examples/line_edit/demo.py
examples/line_edit/demo.py
+2
-2
qfluentwidgets/__init__.py
qfluentwidgets/__init__.py
+1
-1
qfluentwidgets/_rc/images/icons/ChevronDown_black.svg
qfluentwidgets/_rc/images/icons/ChevronDown_black.svg
+1
-1
qfluentwidgets/_rc/images/icons/ChevronDown_white.svg
qfluentwidgets/_rc/images/icons/ChevronDown_white.svg
+1
-2
qfluentwidgets/_rc/qss/dark/combo_box.qss
qfluentwidgets/_rc/qss/dark/combo_box.qss
+2
-2
qfluentwidgets/_rc/qss/light/combo_box.qss
qfluentwidgets/_rc/qss/light/combo_box.qss
+2
-2
qfluentwidgets/_rc/resource.py
qfluentwidgets/_rc/resource.py
+34117
-34117
qfluentwidgets/common/icon.py
qfluentwidgets/common/icon.py
+18
-4
qfluentwidgets/components/dialog_box/color_dialog.py
qfluentwidgets/components/dialog_box/color_dialog.py
+2
-1
qfluentwidgets/components/settings/expand_setting_card.py
qfluentwidgets/components/settings/expand_setting_card.py
+1
-1
qfluentwidgets/components/settings/setting_card.py
qfluentwidgets/components/settings/setting_card.py
+12
-7
qfluentwidgets/components/widgets/__init__.py
qfluentwidgets/components/widgets/__init__.py
+1
-1
qfluentwidgets/components/widgets/combo_box.py
qfluentwidgets/components/widgets/combo_box.py
+200
-85
qfluentwidgets/components/widgets/info_bar.py
qfluentwidgets/components/widgets/info_bar.py
+1
-2
qfluentwidgets/components/widgets/line_edit.py
qfluentwidgets/components/widgets/line_edit.py
+6
-7
qfluentwidgets/components/widgets/menu.py
qfluentwidgets/components/widgets/menu.py
+2
-7
setup.py
setup.py
+1
-1
未找到文件。
examples/combo_box/demo.py
浏览文件 @
019b6612
# coding:utf-8
import
sys
from
PyQt5.QtCore
import
Qt
from
PyQt5.QtWidgets
import
QApplication
,
QWidget
,
QHBoxLayout
from
qfluentwidgets
import
ComboBox
,
setTheme
,
Theme
,
setThemeColor
from
PyQt5.QtWidgets
import
QApplication
,
QWidget
from
qfluentwidgets
import
ComboBox
,
setTheme
,
Theme
,
setThemeColor
,
EditableComboBox
class
Demo
(
QWidget
):
...
...
examples/gallery/app/resource/i18n/gallery_hk.qm
浏览文件 @
019b6612
无法预览此类型文件
examples/gallery/app/resource/i18n/gallery_hk.ts
浏览文件 @
019b6612
...
...
@@ -26,12 +26,12 @@
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
54
"
/>
<
source
>
A
2
-
state
CheckBox
<
/source
>
<
translation
>
雙態
復
選框
<
/translation
>
<
translation
>
雙態
複
選框
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
63
"
/>
<
source
>
A
3
-
state
CheckBox
<
/source
>
<
translation
>
三態
復
選框
<
/translation
>
<
translation
>
三態
複
選框
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
74
"
/>
...
...
@@ -39,34 +39,34 @@
<
translation
>
下拉框
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
96
"
/>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
112
"
/>
<
source
>
A
group
of
RadioButton
controls
in
a
button
group
<
/source
>
<
translation
>
單選按鈕
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
1
07
"
/>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
1
23
"
/>
<
source
>
A
simple
horizontal
slider
<
/source
>
<
translation
>
水平滑動條
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
1
16
"
/>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
1
32
"
/>
<
source
>
A
simple
switch
button
<
/source
>
<
translation
>
開關按鈕
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
1
26
"
/>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
1
42
"
/>
<
source
>
Off
<
/source
>
<
translation
>
關
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
1
24
"
/>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
1
40
"
/>
<
source
>
On
<
/source
>
<
translation
>
開
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
23
"
/>
<
source
>
Standard
push
button
<
/source
>
<
translation
>
標
准
按鈕
<
/translation
>
<
translation
>
標
準
按鈕
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
40
"
/>
...
...
@@ -76,12 +76,12 @@
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
54
"
/>
<
source
>
Two
-
state
CheckBox
<
/source
>
<
translation
>
雙態
復
選框
<
/translation
>
<
translation
>
雙態
複
選框
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
61
"
/>
<
source
>
Three
-
state
CheckBox
<
/source
>
<
translation
>
三態
復
選框
<
/translation
>
<
translation
>
三態
複
選框
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
47
"
/>
...
...
@@ -89,19 +89,39 @@
<
translation
>
GItHub
主頁
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
85
"
/>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
101
"
/>
<
source
>
Star
Platinum
<
/source
>
<
translation
>
白金之星
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
86
"
/>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
102
"
/>
<
source
>
Crazy
Diamond
<
/source
>
<
translation
>
瘋狂
鉆
石
<
/translation
>
<
translation
>
瘋狂
鑽
石
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
87
"
/>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
103
"
/>
<
source
>
Soft
and
Wet
<
/source
>
<
translation
>
軟又濕
<
/translation
>
<
translation
>
軟又溼
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
82
"
/>
<
source
>
Gold
Experience
<
/source
>
<
translation
>
黃金體驗
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
82
"
/>
<
source
>
Sticky
Fingers
<
/source
>
<
translation
>
鋼鏈手指
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
88
"
/>
<
source
>
Choose
your
stand
<
/source
>
<
translation
>
選擇你的替身
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
90
"
/>
<
source
>
An
editable
ComboBox
<
/source
>
<
translation
>
可編輯的下拉框
<
/translation
>
<
/message
>
<
/context
>
<
context
>
...
...
@@ -158,7 +178,7 @@
<
context
>
<
name
>
IconCardView
<
/name
>
<
message
>
<
location
filename
=
"
../../view/icon_interface.py
"
line
=
"
12
6
"
/>
<
location
filename
=
"
../../view/icon_interface.py
"
line
=
"
12
3
"
/>
<
source
>
Fluent
Icons
Library
<
/source
>
<
translation
>
流暢圖標庫
<
/translation
>
<
/message
>
...
...
@@ -166,12 +186,12 @@
<
context
>
<
name
>
IconInfoPanel
<
/name
>
<
message
>
<
location
filename
=
"
../../view/icon_interface.py
"
line
=
"
8
4
"
/>
<
location
filename
=
"
../../view/icon_interface.py
"
line
=
"
8
1
"
/>
<
source
>
Icon
name
<
/source
>
<
translation
>
圖標名字
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/icon_interface.py
"
line
=
"
8
6
"
/>
<
location
filename
=
"
../../view/icon_interface.py
"
line
=
"
8
3
"
/>
<
source
>
Enum
member
<
/source
>
<
translation
>
枚舉成員
<
/translation
>
<
/message
>
...
...
@@ -206,7 +226,7 @@
<
message
>
<
location
filename
=
"
../../view/layout_interface.py
"
line
=
"
37
"
/>
<
source
>
Crazy
diamond
<
/source
>
<
translation
>
瘋狂
鉆
石
<
/translation
>
<
translation
>
瘋狂
鑽
石
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/layout_interface.py
"
line
=
"
38
"
/>
...
...
@@ -242,9 +262,9 @@
<
context
>
<
name
>
LineEdit
<
/name
>
<
message
>
<
location
filename
=
"
../../view/icon_interface.py
"
line
=
"
2
4
"
/>
<
location
filename
=
"
../../view/icon_interface.py
"
line
=
"
2
1
"
/>
<
source
>
Search
icons
<
/source
>
<
translation
>
搜
索圖標
<
/translation
>
<
translation
>
蒐
索圖標
<
/translation
>
<
/message
>
<
/context
>
<
context
>
...
...
@@ -297,7 +317,7 @@
<
message
>
<
location
filename
=
"
../../view/main_window.py
"
line
=
"
255
"
/>
<
source
>
You
clicked
a
customized
navigation
widget
.
You
can
add
more
custom
widgets
by
calling
`NavigationInterface.addWidget()`
😉
<
/source
>
<
translation
>
妳點擊了一個自定義的導航項
。
妳
可以通過
`NavigationInterface.addWidget()`
添加更多的自定義導航項
。
<
/translation
>
<
translation
>
你點擊了一個自定義的導航項
。
你
可以通過
`NavigationInterface.addWidget()`
添加更多的自定義導航項
。
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/main_window.py
"
line
=
"
200
"
/>
...
...
@@ -315,7 +335,7 @@
<
message
>
<
location
filename
=
"
../../view/material_interface.py
"
line
=
"
29
"
/>
<
source
>
Acrylic
label
<
/source
>
<
translation
>
亞克力標
簽
<
/translation
>
<
translation
>
亞克力標
籤
<
/translation
>
<
/message
>
<
/context
>
<
context
>
...
...
@@ -333,7 +353,7 @@
<
message
>
<
location
filename
=
"
../../view/menu_interface.py
"
line
=
"
36
"
/>
<
source
>
Copy
<
/source
>
<
translation
>
復制
<
/translation
>
<
translation
>
複製
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/menu_interface.py
"
line
=
"
37
"
/>
...
...
@@ -353,7 +373,7 @@
<
message
>
<
location
filename
=
"
../../view/menu_interface.py
"
line
=
"
49
"
/>
<
source
>
Paste
<
/source
>
<
translation
>
黏
貼
<
/translation
>
<
translation
>
粘
貼
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/menu_interface.py
"
line
=
"
49
"
/>
...
...
@@ -449,7 +469,7 @@
<
message
>
<
location
filename
=
"
../../view/setting_interface.py
"
line
=
"
56
"
/>
<
source
>
Change
the
appearance
of
your
application
<
/source
>
<
translation
>
調整
妳
的應用的外觀
<
/translation
>
<
translation
>
調整
你
的應用的外觀
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/setting_interface.py
"
line
=
"
56
"
/>
...
...
@@ -474,12 +494,12 @@
<
message
>
<
location
filename
=
"
../../view/setting_interface.py
"
line
=
"
67
"
/>
<
source
>
Change
the
theme
color
of
you
application
<
/source
>
<
translation
>
調整
妳
的應用的主題色
<
/translation
>
<
translation
>
調整
你
的應用的主題色
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/setting_interface.py
"
line
=
"
74
"
/>
<
source
>
Interface
zoom
<
/source
>
<
translation
>
界
面
縮放
<
/translation
>
<
translation
>
界
麵
縮放
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/setting_interface.py
"
line
=
"
74
"
/>
...
...
@@ -494,7 +514,7 @@
<
message
>
<
location
filename
=
"
../../view/setting_interface.py
"
line
=
"
85
"
/>
<
source
>
Set
your
preferred
language
for
UI
<
/source
>
<
translation
>
選擇界
面
所使用的語言
<
/translation
>
<
translation
>
選擇界
麵
所使用的語言
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/setting_interface.py
"
line
=
"
95
"
/>
...
...
@@ -524,7 +544,7 @@
<
message
>
<
location
filename
=
"
../../view/setting_interface.py
"
line
=
"
108
"
/>
<
source
>
The
new
version
will
be
more
stable
and
have
more
features
<
/source
>
<
translation
>
新版本將更加穩定
併
擁有更多功能
(
建議啟用此選項
)
<
/translation
>
<
translation
>
新版本將更加穩定
並
擁有更多功能
(
建議啟用此選項
)
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/setting_interface.py
"
line
=
"
134
"
/>
...
...
@@ -534,7 +554,7 @@
<
message
>
<
location
filename
=
"
../../view/setting_interface.py
"
line
=
"
118
"
/>
<
source
>
Open
help
page
<
/source
>
<
translation
>
打開幫助頁
面
<
/translation
>
<
translation
>
打開幫助頁
麵
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/setting_interface.py
"
line
=
"
118
"
/>
...
...
@@ -544,7 +564,7 @@
<
message
>
<
location
filename
=
"
../../view/setting_interface.py
"
line
=
"
118
"
/>
<
source
>
Discover
new
features
and
learn
useful
tips
about
PyQt
-
Fluent
-
Widgets
<
/source
>
<
translation
>
發現新功能併
了解有關
PyQt
-
Fluent
-
Widgets
的使用技巧
<
/translation
>
<
translation
>
髮現新功能並
了解有關
PyQt
-
Fluent
-
Widgets
的使用技巧
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/setting_interface.py
"
line
=
"
127
"
/>
...
...
@@ -597,7 +617,7 @@
<
message
>
<
location
filename
=
"
../../view/status_info_interface.py
"
line
=
"
50
"
/>
<
source
>
A
label
with
a
ToolTip
<
/source
>
<
translation
>
帶有工具提示的標
簽
<
/translation
>
<
translation
>
帶有工具提示的標
籤
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/status_info_interface.py
"
line
=
"
145
"
/>
...
...
@@ -627,7 +647,7 @@
<
message
>
<
location
filename
=
"
../../view/status_info_interface.py
"
line
=
"
149
"
/>
<
source
>
Please
wait
patiently
<
/source
>
<
translation
>
心急吃不了熱
豆
腐
,
請耐心等待哦
~<
/translation
>
<
translation
>
心急吃不了熱
荳
腐
,
請耐心等待哦
~<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/status_info_interface.py
"
line
=
"
151
"
/>
...
...
@@ -662,7 +682,7 @@
<
message
>
<
location
filename
=
"
../../view/status_info_interface.py
"
line
=
"
92
"
/>
<
source
>
When
you
look
long
into
an
abyss
,
the
abyss
looks
into
you
.
<
/source
>
<
translation
>
當
妳長時間凝視深淵時
,
深淵也在凝視妳
。
<
/translation
>
<
translation
>
當
你長時間凝視深淵時
,
深淵也在凝視你
。
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/status_info_interface.py
"
line
=
"
104
"
/>
...
...
@@ -692,7 +712,7 @@
<
message
>
<
location
filename
=
"
../../view/status_info_interface.py
"
line
=
"
74
"
/>
<
source
>
My
name
is
kira
yoshikake
,
33
years
old
.
Living
in
the
villa
area
northeast
of
duwangting
,
unmarried
.
I
work
in
Guiyou
chain
store
.
Every
day
I
have
to
work
overtime
until
8
p
.
m
.
to
go
home
.
I
don
&
apos
;
t
smoke
.
The
wine
is
only
for
a
taste
.
Sleep
at
11
p
.
m
.
for
8
hours
a
day
.
Before
I
go
to
bed
,
I
must
drink
a
cup
of
warm
milk
,
then
do
20
minutes
of
soft
exercise
,
get
on
the
bed
,
and
immediately
fall
asleep
.
Never
leave
fatigue
and
stress
until
the
next
day
.
Doctors
say
I
&
apos
;
m
normal
.
<
/source
>
<
translation
>
我的名字叫吉良吉影
,
33
歲
。
住在杜王町東北部的別墅區一帶
,
未婚
。
我在龜友連鎖店服務
。
每天都要加班到晚上8點才能回家
。
我不抽
煙
,
酒僅止於淺嘗
。
晚上11點睡
,
每天要睡足8個小時
。
睡前
,
我一定喝一杯溫牛奶
,
然後做20分鐘的柔軟操
,
上了床
,
馬上熟睡
。
一覺到天亮
,
決不把疲勞和壓力留到第二天
。
醫生都說
我很正常
。
<
/translation
>
<
translation
>
我的名字叫吉良吉影
,
33
歲
。
住在杜王町東北部的別墅區一帶
,
未婚
。
我在龜友連鎖店服務
。
每天都要加班到晚上8點才能回家
。
我不抽
菸
,
酒僅止於淺嚐
。
晚上11點睡
,
每天要睡足8個小時
。
睡前
,
我一定喝一盃溫牛奶
,
然後做20分鐘的柔軟操
,
上了床
,
馬上熟睡
。
一覺到天亮
,
決不把疲勞和壓力留到第二天
。
醫生都説
我很正常
。
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/status_info_interface.py
"
line
=
"
156
"
/>
...
...
@@ -702,12 +722,12 @@
<
message
>
<
location
filename
=
"
../../view/status_info_interface.py
"
line
=
"
156
"
/>
<
source
>
Believe
in
the
spin
,
just
keep
believing
!<
/source
>
<
translation
>
相信回旋吧
,
只
管相信就是了
!
<
/translation
>
<
translation
>
相信回旋吧
,
隻
管相信就是了
!
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/status_info_interface.py
"
line
=
"
168
"
/>
<
source
>
With
respect
,
let
&
apos
;
s
advance
towards
a
new
stage
of
the
spin
.
<
/source
>
<
translation
>
錶達敬意吧
,
錶達出敬意
,
然後邁嚮
回旋的另一個全新階段
!
<
/translation
>
<
translation
>
表達敬意吧
,
表達出敬意
,
然後邁向
回旋的另一個全新階段
!
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/status_info_interface.py
"
line
=
"
179
"
/>
...
...
@@ -722,7 +742,7 @@
<
message
>
<
location
filename
=
"
../../view/status_info_interface.py
"
line
=
"
57
"
/>
<
source
>
The
Anthem
of
man
is
the
Anthem
of
courage
.
<
/source
>
<
translation
>
人類的
贊歌就是勇氣的贊
歌
!
<
/translation
>
<
translation
>
人類的
讚歌就是勇氣的讚
歌
!
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/status_info_interface.py
"
line
=
"
102
"
/>
...
...
@@ -767,7 +787,7 @@
<
message
>
<
location
filename
=
"
../../view/status_info_interface.py
"
line
=
"
201
"
/>
<
source
>
Don
&
apos
;
t
have
any
strange
expectations
of
me
.
<
/source
>
<
translation
>
別對我抱有什
麽
奇怪的期待
<
/translation
>
<
translation
>
別對我抱有什
麼
奇怪的期待
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/status_info_interface.py
"
line
=
"
212
"
/>
...
...
@@ -783,42 +803,42 @@
<
context
>
<
name
>
TextInterface
<
/name
>
<
message
>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
2
0
"
/>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
2
1
"
/>
<
source
>
ko
no
dio
da
!
<
/source
>
<
translation
><
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
2
2
"
/>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
2
3
"
/>
<
source
>
A
LineEdit
with
a
clear
button
<
/source
>
<
translation
>
帶清空按鈕的
LineEdit
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
3
6
"
/>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
3
7
"
/>
<
source
>
A
DoubleSpinBox
with
a
spin
button
<
/source
>
<
translation
>
帶調節按鈕的
DoubleSpinBox
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
4
3
"
/>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
4
4
"
/>
<
source
>
A
DateEdit
with
a
spin
button
<
/source
>
<
translation
>
帶調節按鈕的
DateEdit
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
5
0
"
/>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
5
1
"
/>
<
source
>
A
TimeEdit
with
a
spin
button
<
/source
>
<
translation
>
帶調節按鈕的
TimeEdit
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
5
7
"
/>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
5
8
"
/>
<
source
>
A
DateTimeEdit
with
a
spin
button
<
/source
>
<
translation
>
帶調節按鈕的
DateTimeEdit
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
29
"
/>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
30
"
/>
<
source
>
A
SpinBox
with
a
spin
button
<
/source
>
<
translation
>
帶調節按鈕的
SpinBox
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
6
8
"
/>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
6
9
"
/>
<
source
>
A
simple
TextEdit
<
/source
>
<
translation
>
富文本框
<
/translation
>
<
/message
>
...
...
examples/gallery/app/resource/i18n/gallery_zh.qm
浏览文件 @
019b6612
无法预览此类型文件
examples/gallery/app/resource/i18n/gallery_zh.ts
浏览文件 @
019b6612
...
...
@@ -39,27 +39,27 @@
<
translation
>
下拉框
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
96
"
/>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
112
"
/>
<
source
>
A
group
of
RadioButton
controls
in
a
button
group
<
/source
>
<
translation
>
单选按钮
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
1
07
"
/>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
1
23
"
/>
<
source
>
A
simple
horizontal
slider
<
/source
>
<
translation
>
水平滑动条
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
1
16
"
/>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
1
32
"
/>
<
source
>
A
simple
switch
button
<
/source
>
<
translation
>
开关按钮
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
1
26
"
/>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
1
42
"
/>
<
source
>
Off
<
/source
>
<
translation
>
关
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
1
24
"
/>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
1
40
"
/>
<
source
>
On
<
/source
>
<
translation
>
开
<
/translation
>
<
/message
>
...
...
@@ -89,20 +89,40 @@
<
translation
>
GItHub
主页
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
85
"
/>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
101
"
/>
<
source
>
Star
Platinum
<
/source
>
<
translation
>
白金之星
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
86
"
/>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
102
"
/>
<
source
>
Crazy
Diamond
<
/source
>
<
translation
>
疯狂钻石
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
87
"
/>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
103
"
/>
<
source
>
Soft
and
Wet
<
/source
>
<
translation
>
软又湿
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
82
"
/>
<
source
>
Gold
Experience
<
/source
>
<
translation
>
黄金体验
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
82
"
/>
<
source
>
Sticky
Fingers
<
/source
>
<
translation
>
钢链手指
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
88
"
/>
<
source
>
Choose
your
stand
<
/source
>
<
translation
>
选择你的替身
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/basic_input_interface.py
"
line
=
"
90
"
/>
<
source
>
An
editable
ComboBox
<
/source
>
<
translation
>
可编辑的下拉框
<
/translation
>
<
/message
>
<
/context
>
<
context
>
<
name
>
DialogInterface
<
/name
>
...
...
@@ -158,7 +178,7 @@
<
context
>
<
name
>
IconCardView
<
/name
>
<
message
>
<
location
filename
=
"
../../view/icon_interface.py
"
line
=
"
12
6
"
/>
<
location
filename
=
"
../../view/icon_interface.py
"
line
=
"
12
3
"
/>
<
source
>
Fluent
Icons
Library
<
/source
>
<
translation
>
流畅图标库
<
/translation
>
<
/message
>
...
...
@@ -166,12 +186,12 @@
<
context
>
<
name
>
IconInfoPanel
<
/name
>
<
message
>
<
location
filename
=
"
../../view/icon_interface.py
"
line
=
"
8
4
"
/>
<
location
filename
=
"
../../view/icon_interface.py
"
line
=
"
8
1
"
/>
<
source
>
Icon
name
<
/source
>
<
translation
>
图标名字
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/icon_interface.py
"
line
=
"
8
6
"
/>
<
location
filename
=
"
../../view/icon_interface.py
"
line
=
"
8
3
"
/>
<
source
>
Enum
member
<
/source
>
<
translation
>
枚举成员
<
/translation
>
<
/message
>
...
...
@@ -242,7 +262,7 @@
<
context
>
<
name
>
LineEdit
<
/name
>
<
message
>
<
location
filename
=
"
../../view/icon_interface.py
"
line
=
"
2
4
"
/>
<
location
filename
=
"
../../view/icon_interface.py
"
line
=
"
2
1
"
/>
<
source
>
Search
icons
<
/source
>
<
translation
>
搜索图标
<
/translation
>
<
/message
>
...
...
@@ -783,42 +803,42 @@
<
context
>
<
name
>
TextInterface
<
/name
>
<
message
>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
2
0
"
/>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
2
1
"
/>
<
source
>
ko
no
dio
da
!
<
/source
>
<
translation
><
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
2
2
"
/>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
2
3
"
/>
<
source
>
A
LineEdit
with
a
clear
button
<
/source
>
<
translation
>
带清空按钮的
LineEdit
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
3
6
"
/>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
3
7
"
/>
<
source
>
A
DoubleSpinBox
with
a
spin
button
<
/source
>
<
translation
>
带调节按钮的
DoubleSpinBox
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
4
3
"
/>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
4
4
"
/>
<
source
>
A
DateEdit
with
a
spin
button
<
/source
>
<
translation
>
带调节按钮的
DateEdit
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
5
0
"
/>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
5
1
"
/>
<
source
>
A
TimeEdit
with
a
spin
button
<
/source
>
<
translation
>
带调节按钮的
TimeEdit
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
5
7
"
/>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
5
8
"
/>
<
source
>
A
DateTimeEdit
with
a
spin
button
<
/source
>
<
translation
>
带调节按钮的
DateTimeEdit
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
29
"
/>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
30
"
/>
<
source
>
A
SpinBox
with
a
spin
button
<
/source
>
<
translation
>
带调节按钮的
SpinBox
<
/translation
>
<
/message
>
<
message
>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
6
8
"
/>
<
location
filename
=
"
../../view/text_interface.py
"
line
=
"
6
9
"
/>
<
source
>
A
simple
TextEdit
<
/source
>
<
translation
>
富文本框
<
/translation
>
<
/message
>
...
...
examples/gallery/app/view/basic_input_interface.py
浏览文件 @
019b6612
...
...
@@ -2,7 +2,7 @@
from
PyQt5.QtCore
import
Qt
,
QSize
from
PyQt5.QtWidgets
import
QWidget
,
QVBoxLayout
,
QButtonGroup
from
qfluentwidgets
import
(
PushButton
,
ToolButton
,
PrimaryPushButton
,
HyperlinkButton
,
ComboBox
,
RadioButton
,
CheckBox
,
Slider
,
SwitchButton
)
ComboBox
,
RadioButton
,
CheckBox
,
Slider
,
SwitchButton
,
EditableComboBox
)
from
.gallery_interface
import
GalleryInterface
from
..common.translator
import
Translator
...
...
@@ -77,6 +77,22 @@ class BasicInputInterface(GalleryInterface):
'https://github.com/zhiyiYo/PyQt-Fluent-Widgets/blob/master/examples/combo_box/demo.py'
)
# editable combo box
comboBox
=
EditableComboBox
()
comboBox
.
addItems
([
self
.
tr
(
'Star Platinum'
),
self
.
tr
(
'Crazy Diamond'
),
self
.
tr
(
"Gold Experience"
),
self
.
tr
(
'Sticky Fingers'
),
])
comboBox
.
setPlaceholderText
(
self
.
tr
(
'Choose your stand'
))
comboBox
.
setMinimumWidth
(
210
)
self
.
addExampleCard
(
self
.
tr
(
'An editable ComboBox'
),
comboBox
,
'https://github.com/zhiyiYo/PyQt-Fluent-Widgets/blob/master/examples/combo_box/demo.py'
)
# radio button
radioWidget
=
QWidget
()
radioLayout
=
QVBoxLayout
(
radioWidget
)
...
...
examples/gallery/app/view/text_interface.py
浏览文件 @
019b6612
...
...
@@ -17,7 +17,8 @@ class TextInterface(GalleryInterface):
)
# spin box
lineEdit
=
LineEdit
(
self
.
tr
(
'ko no dio da!'
),
self
)
lineEdit
=
LineEdit
(
self
)
lineEdit
.
setText
(
self
.
tr
(
'ko no dio da!'
))
lineEdit
.
setClearButtonEnabled
(
True
)
self
.
addExampleCard
(
title
=
self
.
tr
(
"A LineEdit with a clear button"
),
...
...
examples/line_edit/demo.py
浏览文件 @
019b6612
...
...
@@ -10,7 +10,7 @@ class Demo(QWidget):
def
__init__
(
self
):
super
().
__init__
()
self
.
lineEdit
=
LineEdit
(
''
,
self
)
self
.
lineEdit
=
LineEdit
(
self
)
self
.
button
=
PushButton
(
'按钮'
,
self
)
self
.
textEdit
=
TextEdit
(
self
)
...
...
@@ -18,7 +18,7 @@ class Demo(QWidget):
self
.
textEdit
.
move
(
110
,
200
)
self
.
lineEdit
.
move
(
110
,
50
)
self
.
button
.
move
(
320
,
52
)
self
.
lineEdit
.
resize
(
200
,
33
)
self
.
lineEdit
.
setClearButtonEnabled
(
True
)
...
...
qfluentwidgets/__init__.py
浏览文件 @
019b6612
...
...
@@ -12,7 +12,7 @@ Examples are available at https://github.com/zhiyiYo/PyQt-Fluent-Widgets/tree/ma
:license: GPLv3, see LICENSE for more details.
"""
__version__
=
"0.6.
3
"
__version__
=
"0.6.
4
"
from
.components
import
*
from
.common
import
*
...
...
qfluentwidgets/_rc/images/icons/ChevronDown_black.svg
浏览文件 @
019b6612
...
...
@@ -2,7 +2,7 @@
<svg
xmlns=
"http://www.w3.org/2000/svg"
height=
"16"
width=
"16"
viewBox=
"0 0 16 16"
>
<g>
<path
id=
"path1"
transform=
"rotate(0,8,8) translate(
0,1.19976567076743
) scale(0.0374926772114821,0.0374926772114821) "
transform=
"rotate(0,8,8) translate(
-1.8,-1.5
) scale(0.0374926772114821,0.0374926772114821) "
fill=
"#000000"
d=
"M106.75,170.5L111.1875,170.90625 115,172.125 118.4375,174.15625 121.75,177 256,311.25 390.25,177 393.625,174.156265258789 397.25,172.125 401.125,170.90625 405.25,170.5 409.59375,170.9375 413.625,172.25 417.25,174.281265258789 420.375,176.875 422.96875,180.000015258789 425,183.625 426.312469482422,187.65625 426.75,192 426.359344482422,196.21875 425.187469482422,200.125 423.234344482422,203.71875 420.5,207 271,356.5 267.71875,359.234375 264.125,361.1875 260.21875,362.359375 256,362.75 251.78125,362.359375 247.875,361.1875 244.28125,359.234375 241,356.5 91.5,207 88.765625,203.71875 86.8125,200.125 85.640625,196.21875 85.25,192 85.6875,187.65625 87,183.625 89.03125,180.000015258789 91.625,176.875 94.75,174.281265258789 98.375,172.25 102.40625,170.9375 106.75,170.5z"
/>
</g>
...
...
qfluentwidgets/_rc/images/icons/ChevronDown_white.svg
浏览文件 @
019b6612
<?xml version="1.0" encoding="utf-8"?>
<svg
xmlns=
"http://www.w3.org/2000/svg"
height=
"16"
width=
"16"
viewBox=
"0 0 16 16"
>
<g>
<path
id=
"path1"
transform=
"rotate(0,8,8) translate(
0,1.19976567076743
) scale(0.0374926772114821,0.0374926772114821) "
fill=
"#FFFFFF"
d=
"M106.75,170.5L111.1875,170.90625 115,172.125 118.4375,174.15625 121.75,177 256,311.25 390.25,177 393.625,174.156265258789 397.25,172.125 401.125,170.90625 405.25,170.5 409.59375,170.9375 413.625,172.25 417.25,174.281265258789 420.375,176.875 422.96875,180.000015258789 425,183.625 426.312469482422,187.65625 426.75,192 426.359344482422,196.21875 425.187469482422,200.125 423.234344482422,203.71875 420.5,207 271,356.5 267.71875,359.234375 264.125,361.1875 260.21875,362.359375 256,362.75 251.78125,362.359375 247.875,361.1875 244.28125,359.234375 241,356.5 91.5,207 88.765625,203.71875 86.8125,200.125 85.640625,196.21875 85.25,192 85.6875,187.65625 87,183.625 89.03125,180.000015258789 91.625,176.875 94.75,174.281265258789 98.375,172.25 102.40625,170.9375 106.75,170.5z"
/>
<path
id=
"path1"
transform=
"rotate(0,8,8) translate(
-1.8,-1.5
) scale(0.0374926772114821,0.0374926772114821) "
fill=
"#FFFFFF"
d=
"M106.75,170.5L111.1875,170.90625 115,172.125 118.4375,174.15625 121.75,177 256,311.25 390.25,177 393.625,174.156265258789 397.25,172.125 401.125,170.90625 405.25,170.5 409.59375,170.9375 413.625,172.25 417.25,174.281265258789 420.375,176.875 422.96875,180.000015258789 425,183.625 426.312469482422,187.65625 426.75,192 426.359344482422,196.21875 425.187469482422,200.125 423.234344482422,203.71875 420.5,207 271,356.5 267.71875,359.234375 264.125,361.1875 260.21875,362.359375 256,362.75 251.78125,362.359375 247.875,361.1875 244.28125,359.234375 241,356.5 91.5,207 88.765625,203.71875 86.8125,200.125 85.640625,196.21875 85.25,192 85.6875,187.65625 87,183.625 89.03125,180.000015258789 91.625,176.875 94.75,174.281265258789 98.375,172.25 102.40625,170.9375 106.75,170.5z"
/>
</g>
</svg>
qfluentwidgets/_rc/qss/dark/combo_box.qss
浏览文件 @
019b6612
...
...
@@ -30,7 +30,7 @@ ComboBoxMenu>MenuActionListWidget {
ComboBoxMenu>MenuActionListWidget::item {
margin-top: 4px;
padding-left: 0px;
padding-left:
1
0px;
padding-right: 10px;
border-radius: 5px;
border: none;
...
...
@@ -38,7 +38,7 @@ ComboBoxMenu>MenuActionListWidget::item {
}
ComboBoxMenu>MenuActionListWidget::disbled {
padding-left: 0px;
padding-left:
1
0px;
padding-right: 10px;
border-radius: 5px;
border: none;
...
...
qfluentwidgets/_rc/qss/light/combo_box.qss
浏览文件 @
019b6612
...
...
@@ -30,14 +30,14 @@ ComboBoxMenu>MenuActionListWidget {
ComboBoxMenu>MenuActionListWidget::item {
margin-top: 4px;
padding-left: 0px;
padding-left:
1
0px;
padding-right: 10px;
border-radius: 5px;
border: none;
}
ComboBoxMenu>MenuActionListWidget::item:disbaled {
padding-left: 0px;
padding-left:
1
0px;
padding-right: 10px;
border-radius: 5px;
border: none;
...
...
qfluentwidgets/_rc/resource.py
浏览文件 @
019b6612
此差异已折叠。
点击以展开。
qfluentwidgets/common/icon.py
浏览文件 @
019b6612
...
...
@@ -113,7 +113,7 @@ def writeSvg(iconPath: str, indexes=None, **attributes):
return
dom
.
toString
()
def
drawIcon
(
icon
,
painter
,
rect
):
def
drawIcon
(
icon
,
painter
,
rect
,
**
attributes
):
""" draw icon
Parameters
...
...
@@ -126,9 +126,12 @@ def drawIcon(icon, painter, rect):
rect: QRect | QRectF
the rect to render icon
**attribute:
the attribute of svg icon
"""
if
isinstance
(
icon
,
FluentIconBase
):
icon
.
render
(
painter
,
rect
)
icon
.
render
(
painter
,
rect
,
**
attributes
)
else
:
icon
=
QIcon
(
icon
)
rect
=
QRectF
(
rect
).
toRect
()
...
...
@@ -165,7 +168,7 @@ class FluentIconBase:
"""
return
QIcon
(
self
.
path
(
theme
))
def
render
(
self
,
painter
,
rect
,
theme
=
Theme
.
AUTO
):
def
render
(
self
,
painter
,
rect
,
theme
=
Theme
.
AUTO
,
indexes
=
None
,
**
attributes
):
""" draw svg icon
Parameters
...
...
@@ -181,8 +184,19 @@ class FluentIconBase:
* `Theme.Light`: black icon
* `Theme.DARK`: white icon
* `Theme.AUTO`: icon color depends on `config.theme`
indexes: List[int]
the svg path to be modified
**attributes:
the attributes of modified path
"""
drawSvgIcon
(
self
.
path
(
theme
),
painter
,
rect
)
if
attributes
:
svg
=
writeSvg
(
self
.
path
(
theme
),
indexes
,
**
attributes
).
encode
()
else
:
svg
=
self
.
path
(
theme
)
drawSvgIcon
(
svg
,
painter
,
rect
)
class
FluentIcon
(
FluentIconBase
,
Enum
):
...
...
qfluentwidgets/components/dialog_box/color_dialog.py
浏览文件 @
019b6612
...
...
@@ -134,7 +134,8 @@ class ColorLineEdit(LineEdit):
valueChanged
=
pyqtSignal
(
str
)
def
__init__
(
self
,
value
,
parent
=
None
):
super
().
__init__
(
str
(
value
),
parent
)
super
().
__init__
(
parent
)
self
.
setText
(
str
(
value
))
self
.
setFixedSize
(
136
,
33
)
self
.
setClearButtonEnabled
(
True
)
self
.
setValidator
(
QIntValidator
(
0
,
255
,
self
))
...
...
qfluentwidgets/components/settings/expand_setting_card.py
浏览文件 @
019b6612
...
...
@@ -46,7 +46,7 @@ class ExpandButton(QAbstractButton):
# draw icon
painter
.
translate
(
self
.
width
()
//
2
,
self
.
height
()
//
2
)
painter
.
rotate
(
self
.
__angle
)
FIF
.
ARROW_DOWN
.
render
(
painter
,
QRectF
(
-
6
,
-
6
,
9.6
,
9.6
))
FIF
.
ARROW_DOWN
.
render
(
painter
,
QRectF
(
-
5
,
-
5
,
9.6
,
9.6
))
def
enterEvent
(
self
,
e
):
self
.
setHover
(
True
)
...
...
qfluentwidgets/components/settings/setting_card.py
浏览文件 @
019b6612
...
...
@@ -13,7 +13,7 @@ from ..widgets.slider import Slider
from
..widgets.icon_widget
import
IconWidget
from
..widgets.button
import
HyperlinkButton
from
...common.style_sheet
import
FluentStyleSheet
from
...common.config
import
qconfig
,
isDarkTheme
,
ConfigItem
from
...common.config
import
qconfig
,
isDarkTheme
,
ConfigItem
,
OptionsConfigItem
from
...common.icon
import
FluentIconBase
...
...
@@ -357,7 +357,7 @@ class ColorSettingCard(SettingCard):
class
ComboBoxSettingCard
(
SettingCard
):
""" Setting card with a combo box """
def
__init__
(
self
,
configItem
,
icon
:
Union
[
str
,
QIcon
,
FluentIconBase
],
title
,
content
=
None
,
texts
=
None
,
parent
=
None
):
def
__init__
(
self
,
configItem
:
OptionsConfigItem
,
icon
:
Union
[
str
,
QIcon
,
FluentIconBase
],
title
,
content
=
None
,
texts
=
None
,
parent
=
None
):
"""
Parameters
----------
...
...
@@ -385,16 +385,21 @@ class ComboBoxSettingCard(SettingCard):
self
.
hBoxLayout
.
addWidget
(
self
.
comboBox
,
0
,
Qt
.
AlignRight
)
self
.
hBoxLayout
.
addSpacing
(
16
)
self
.
textToOption
=
{
t
:
o
for
t
,
o
in
zip
(
texts
,
configItem
.
options
)}
self
.
optionToText
=
{
o
:
t
for
o
,
t
in
zip
(
configItem
.
options
,
texts
)}
self
.
comboBox
.
addItems
(
texts
)
for
text
,
option
in
zip
(
texts
,
configItem
.
options
):
self
.
comboBox
.
addItem
(
text
,
userData
=
option
)
self
.
comboBox
.
setCurrentText
(
self
.
optionToText
[
qconfig
.
get
(
configItem
)])
self
.
comboBox
.
current
TextChanged
.
connect
(
self
.
_onCurrentText
Changed
)
self
.
comboBox
.
current
IndexChanged
.
connect
(
self
.
_onCurrentIndex
Changed
)
configItem
.
valueChanged
.
connect
(
self
.
setValue
)
def
_onCurrentTextChanged
(
self
,
text
):
qconfig
.
set
(
self
.
configItem
,
self
.
textToOption
[
text
])
def
_onCurrentIndexChanged
(
self
,
index
:
int
):
qconfig
.
set
(
self
.
configItem
,
self
.
comboBox
.
itemData
(
index
))
def
setValue
(
self
,
value
):
if
value
not
in
self
.
optionToText
:
return
self
.
comboBox
.
setCurrentText
(
self
.
optionToText
[
value
])
qconfig
.
set
(
self
.
configItem
,
value
)
\ No newline at end of file
qfluentwidgets/components/widgets/__init__.py
浏览文件 @
019b6612
from
.button
import
PrimaryPushButton
,
PushButton
,
RadioButton
,
HyperlinkButton
,
ToolButton
from
.check_box
import
CheckBox
from
.combo_box
import
ComboBox
from
.combo_box
import
ComboBox
,
EditableComboBox
from
.line_edit
import
LineEdit
,
TextEdit
,
PlainTextEdit
,
LineEditButton
,
SearchLineEdit
from
.icon_widget
import
IconWidget
from
.label
import
PixmapLabel
...
...
qfluentwidgets/components/widgets/combo_box.py
浏览文件 @
019b6612
# coding:utf-8
from
PyQt5.QtCore
import
Qt
,
pyqtSignal
,
QRect
,
QRectF
,
QPoint
from
PyQt5.QtGui
import
QColor
,
QPainter
,
QCursor
from
PyQt5.QtWidgets
import
QAction
,
QPushButton
,
QWidget
from
typing
import
Dict
,
Union
,
List
,
Iterable
from
PyQt5.QtCore
import
Qt
,
pyqtSignal
,
QRect
,
QRectF
,
QPoint
,
QObject
,
QEvent
from
PyQt5.QtGui
import
QColor
,
QPainter
,
QCursor
,
QIcon
from
PyQt5.QtWidgets
import
QAction
,
QPushButton
,
QWidget
,
QStyledItemDelegate
,
QStyle
from
.menu
import
RoundMenu
from
...common.config
import
isDarkTheme
from
.line_edit
import
LineEdit
,
LineEditButton
from
...common.icon
import
FluentIconBase
,
isDarkTheme
from
...common.icon
import
FluentIcon
as
FIF
from
...common.style_sheet
import
FluentStyleSheet
,
themeColor
class
ComboBox
(
QPushButton
):
""" Combo box """
class
ComboItem
:
""" Combo box item """
def
__init__
(
self
,
text
:
str
,
icon
:
Union
[
str
,
QIcon
,
FluentIconBase
]
=
None
,
userData
=
None
):
""" add item
Parameters
----------
text: str
the text of item
icon: str | QIcon | FluentIconBase
the icon of item
userData: Any
user data
"""
self
.
text
=
text
self
.
userData
=
userData
if
icon
:
self
.
_icon
=
QIcon
(
icon
)
if
isinstance
(
icon
,
str
)
else
icon
else
:
self
.
_icon
=
QIcon
()
@
property
def
icon
(
self
):
if
isinstance
(
self
.
_icon
,
QIcon
):
return
self
.
_icon
return
self
.
_icon
.
icon
()
class
ComboBoxBase
(
QObject
):
""" Combo box base """
currentIndexChanged
=
pyqtSignal
(
int
)
currentTextChanged
=
pyqtSignal
(
str
)
def
__init__
(
self
,
parent
=
None
):
super
().
__init__
(
""
,
parent
)
def
__init__
(
self
,
parent
=
None
,
**
kwargs
):
super
().
__init__
(
parent
=
parent
)
self
.
isHover
=
False
self
.
isPressed
=
False
self
.
items
=
[]
self
.
items
=
[]
# type: List[ComboItem]
self
.
itemMap
=
{}
# type: Dict[str, ComboItem]
self
.
_currentIndex
=
-
1
self
.
dropMenu
=
None
FluentStyleSheet
.
COMBO_BOX
.
apply
(
self
)
def
addItem
(
self
,
text
):
FluentStyleSheet
.
COMBO_BOX
.
apply
(
self
)
self
.
installEventFilter
(
self
)
def
eventFilter
(
self
,
obj
,
e
:
QEvent
):
if
obj
is
self
:
if
e
.
type
()
==
QEvent
.
MouseButtonPress
:
self
.
isPressed
=
True
elif
e
.
type
()
==
QEvent
.
MouseButtonRelease
:
self
.
isPressed
=
False
elif
e
.
type
()
==
QEvent
.
Enter
:
self
.
isHover
=
True
elif
e
.
type
()
==
QEvent
.
Leave
:
self
.
isHover
=
False
return
super
().
eventFilter
(
obj
,
e
)
def
addItem
(
self
,
text
,
icon
:
Union
[
str
,
QIcon
,
FluentIconBase
]
=
None
,
userData
=
None
):
""" add item
Parameters
----------
text: str
the text of item
icon: str | QIcon | FluentIconBase
"""
self
.
items
.
append
(
text
)
if
not
text
or
text
in
self
.
itemMap
:
return
def
addItems
(
self
,
texts
):
item
=
ComboItem
(
text
,
icon
,
userData
)
self
.
itemMap
[
text
]
=
item
self
.
items
.
append
(
item
)
def
addItems
(
self
,
texts
:
Iterable
[
str
]):
""" add items
Parameters
...
...
@@ -42,7 +100,29 @@ class ComboBox(QPushButton):
text: Iterable[str]
the text of item
"""
self
.
items
.
extend
(
texts
)
for
text
in
texts
:
self
.
addItem
(
text
)
def
removeItem
(
self
,
index
:
int
):
""" Removes the item at the given index from the combobox.
This will update the current index if the index is removed.
"""
if
not
0
<=
index
<
len
(
self
.
items
):
return
item
=
self
.
items
[
index
]
self
.
items
.
pop
(
index
)
self
.
itemMap
.
pop
(
item
.
text
)
if
index
<
self
.
currentIndex
():
self
.
_onItemClicked
(
self
.
_currentIndex
-
1
)
elif
index
==
self
.
currentIndex
():
if
index
>
0
:
self
.
_onItemClicked
(
self
.
_currentIndex
-
1
)
else
:
self
.
setCurrentIndex
(
0
)
self
.
currentTextChanged
.
emit
(
self
.
currentText
())
self
.
currentIndexChanged
.
emit
(
0
)
def
currentIndex
(
self
):
return
self
.
_currentIndex
...
...
@@ -55,11 +135,11 @@ class ComboBox(QPushButton):
index: int
current index
"""
if
not
0
<=
index
<
len
(
self
.
items
)
or
self
.
currentIndex
()
==
index
:
if
not
0
<=
index
<
len
(
self
.
items
):
return
self
.
_currentIndex
=
index
self
.
setText
(
self
.
items
[
index
])
self
.
setText
(
self
.
items
[
index
]
.
text
)
def
setText
(
self
,
text
:
str
):
super
().
setText
(
text
)
...
...
@@ -69,7 +149,7 @@ class ComboBox(QPushButton):
if
not
0
<=
self
.
currentIndex
()
<
len
(
self
.
items
):
return
''
return
self
.
items
[
self
.
currentIndex
()]
return
self
.
items
[
self
.
currentIndex
()]
.
text
def
setCurrentText
(
self
,
text
):
""" set the current text displayed in combo box,
...
...
@@ -80,10 +160,10 @@ class ComboBox(QPushButton):
text: str
text displayed in combo box
"""
if
text
not
in
self
.
item
s
or
text
==
self
.
currentText
():
if
text
not
in
self
.
item
Map
or
text
==
self
.
currentText
():
return
self
.
setCurrentIndex
(
self
.
items
.
index
(
text
))
self
.
setCurrentIndex
(
self
.
items
.
index
(
self
.
itemMap
[
text
]
))
def
setItemText
(
self
,
index
,
text
):
""" set the text of item
...
...
@@ -96,35 +176,41 @@ class ComboBox(QPushButton):
text: str
new text of item
"""
if
not
0
<=
index
<
len
(
self
.
items
):
if
text
in
self
.
itemMap
or
not
0
<=
index
<
len
(
self
.
items
):
return
self
.
items
[
index
]
=
text
item
=
self
.
itemMap
.
pop
()
item
.
text
=
text
self
.
itemMap
[
text
]
=
item
if
self
.
currentIndex
()
==
index
:
self
.
setText
(
text
)
def
enterEvent
(
self
,
e
):
self
.
isHover
=
True
self
.
update
()
def
itemData
(
self
,
index
:
int
):
""" Returns the data for the given role in the given index in the combobox """
if
not
0
<=
index
<
len
(
self
.
items
):
return
None
def
leaveEvent
(
self
,
e
):
self
.
isHover
=
False
self
.
update
()
return
self
.
items
[
index
].
userData
def
mousePressEvent
(
self
,
e
):
super
().
mousePressEvent
(
e
)
self
.
isPressed
=
True
self
.
update
()
def
setItemData
(
self
,
index
:
int
,
valu
e
):
""" Sets the data role for the item on the given index in the combobox to the specified value """
if
0
<=
index
<
len
(
self
.
items
):
self
.
items
[
index
].
userData
=
value
def
mouseReleaseEvent
(
self
,
e
):
super
().
mouseReleaseEvent
(
e
)
self
.
isPressed
=
False
self
.
update
()
def
findData
(
self
,
data
):
""" Returns the index of the item containing the given data, otherwise returns -1 """
for
i
,
item
in
enumerate
(
self
.
items
):
if
item
.
userData
==
data
:
return
i
if
self
.
dropMenu
:
self
.
_closeComboMenu
()
else
:
self
.
_showComboMenu
()
return
-
1
def
findText
(
self
,
text
:
str
):
""" Returns the index of the item containing the given text; otherwise returns -1. """
if
text
not
in
self
.
itemMap
:
return
-
1
return
self
.
items
.
index
(
self
.
itemMap
[
text
])
def
_closeComboMenu
(
self
):
if
not
self
.
dropMenu
:
...
...
@@ -145,32 +231,57 @@ class ComboBox(QPushButton):
menu
=
ComboBoxMenu
(
self
)
for
i
,
item
in
enumerate
(
self
.
items
):
menu
.
addAction
(
QAction
(
item
,
triggered
=
lambda
c
,
x
=
i
:
self
.
_onItemClicked
(
x
)))
QAction
(
item
.
icon
,
item
.
text
,
triggered
=
lambda
c
,
x
=
i
:
self
.
_onItemClicked
(
x
)))
menu
.
view
.
setMinimumWidth
(
self
.
width
())
menu
.
adjustSize
()
if
menu
.
view
.
width
()
<
self
.
width
():
menu
.
view
.
setMinimumWidth
(
self
.
width
())
menu
.
adjustSize
()
menu
.
closedSignal
.
connect
(
self
.
_onDropMenuClosed
)
self
.
dropMenu
=
menu
# set the selected item
menu
.
setDefaultAction
(
menu
.
menuActions
()[
self
.
currentIndex
()])
if
self
.
currentIndex
()
>=
0
and
self
.
items
:
menu
.
setDefaultAction
(
menu
.
menuActions
()[
self
.
currentIndex
()])
# show menu
x
=
-
menu
.
width
()
//
2
+
menu
.
layout
().
contentsMargins
().
left
()
+
self
.
width
()
//
2
y
=
self
.
height
()
menu
.
exec
(
self
.
mapToGlobal
(
QPoint
(
x
,
y
)))
def
_toggleComboMenu
(
self
):
if
self
.
dropMenu
:
self
.
_closeComboMenu
()
else
:
self
.
_showComboMenu
()
def
_onItemClicked
(
self
,
index
):
if
index
==
self
.
currentIndex
():
return
self
.
setCurrentIndex
(
index
)
self
.
currentTextChanged
.
emit
(
self
.
currentText
())
self
.
currentIndexChanged
.
emit
(
index
)
self
.
currentTextChanged
.
emit
(
self
.
items
[
index
])
class
ComboBox
(
QPushButton
,
ComboBoxBase
):
""" Combo box """
currentIndexChanged
=
pyqtSignal
(
int
)
currentTextChanged
=
pyqtSignal
(
str
)
def
__init__
(
self
,
parent
=
None
):
super
().
__init__
(
parent
=
parent
)
def
setPlaceholderText
(
self
,
text
:
str
):
self
.
setText
(
text
)
def
mouseReleaseEvent
(
self
,
e
):
super
().
mouseReleaseEvent
(
e
)
self
.
_toggleComboMenu
()
def
paintEvent
(
self
,
e
):
super
().
paintEvent
(
e
)
QPushButton
.
paintEvent
(
self
,
e
)
painter
=
QPainter
(
self
)
painter
.
setRenderHints
(
QPainter
.
Antialiasing
)
if
self
.
isHover
:
...
...
@@ -178,52 +289,60 @@ class ComboBox(QPushButton):
elif
self
.
isPressed
:
painter
.
setOpacity
(
0.7
)
FIF
.
ARROW_DOWN
.
render
(
painter
,
QRectF
(
self
.
width
()
-
22
,
self
.
height
()
/
2
-
6
,
10
,
10
))
rect
=
QRectF
(
self
.
width
()
-
22
,
self
.
height
()
/
2
-
5
,
10
,
10
)
if
isDarkTheme
():
FIF
.
ARROW_DOWN
.
render
(
painter
,
rect
)
else
:
FIF
.
ARROW_DOWN
.
render
(
painter
,
rect
,
fill
=
"#646464"
)
class
ComboBoxMenuItemWidget
(
QWidget
):
"""
Combo box menu item widget
"""
class
EditableComboBox
(
LineEdit
,
ComboBoxBase
):
"""
Editable combo box
"""
def
__init__
(
self
,
item
,
parent
=
None
):
super
().
__init__
(
parent
)
self
.
isPressed
=
False
self
.
item
=
item
self
.
text
=
item
.
text
()
item
.
setText
(
''
)
currentIndexChanged
=
pyqtSignal
(
int
)
currentTextChanged
=
pyqtSignal
(
str
)
def
mousePressEvent
(
self
,
e
):
super
().
mousePressEvent
(
e
)
self
.
isPressed
=
True
self
.
update
()
def
__init__
(
self
,
parent
=
None
):
super
().
__init__
(
parent
=
parent
)
self
.
dropButton
=
LineEditButton
(
FIF
.
ARROW_DOWN
,
self
)
def
mouseReleaseEvent
(
self
,
e
):
super
().
mouseReleaseEvent
(
e
)
self
.
isPressed
=
False
self
.
update
()
self
.
setTextMargins
(
0
,
0
,
29
,
0
)
self
.
dropButton
.
setFixedSize
(
30
,
25
)
self
.
hBoxLayout
.
addWidget
(
self
.
dropButton
,
0
,
Qt
.
AlignRight
)
def
paintEvent
(
self
,
e
):
painter
=
QPainter
(
self
)
painter
.
setRenderHints
(
QPainter
.
Antialiasing
|
QPainter
.
SmoothPixmapTransform
|
QPainter
.
TextAntialiasing
)
self
.
dropButton
.
clicked
.
connect
(
self
.
_toggleComboMenu
)
self
.
textEdited
.
connect
(
self
.
_onTextEdited
)
self
.
returnPressed
.
connect
(
lambda
:
self
.
addItem
(
self
.
text
()))
if
self
.
isPressed
:
painter
.
setOpacity
(
0.7
)
def
_onTextEdited
(
self
,
text
:
str
):
if
text
not
in
self
.
itemMap
:
self
.
_currentIndex
=
-
1
else
:
self
.
_currentIndex
=
self
.
items
.
index
(
self
.
itemMap
[
text
])
# draw text
isLight
=
not
isDarkTheme
()
painter
.
setPen
(
Qt
.
black
if
isLight
else
Qt
.
white
)
painter
.
setFont
(
self
.
item
.
font
())
painter
.
drawText
(
QRect
(
12
,
0
,
self
.
width
()
-
10
,
self
.
height
()),
Qt
.
AlignVCenter
,
self
.
text
)
self
.
currentTextChanged
.
emit
(
text
)
# draw indicator
if
not
self
.
item
.
isSelected
():
def
_onDropMenuClosed
(
self
):
self
.
dropMenu
=
None
class
ComboMenuItemDelegate
(
QStyledItemDelegate
):
""" Combo box drop menu item delegate """
def
paint
(
self
,
painter
:
QPainter
,
option
,
index
):
super
().
paint
(
painter
,
option
,
index
)
if
not
option
.
state
&
QStyle
.
State_Selected
:
return
painter
.
save
()
painter
.
setRenderHints
(
QPainter
.
Antialiasing
|
QPainter
.
SmoothPixmapTransform
|
QPainter
.
TextAntialiasing
)
painter
.
setPen
(
Qt
.
NoPen
)
painter
.
setBrush
(
themeColor
())
painter
.
drawRoundedRect
(
0
,
8
,
3
,
16
,
1.5
,
1.5
)
painter
.
drawRoundedRect
(
0
,
11
+
option
.
rect
.
y
(),
3
,
15
,
1.5
,
1.5
)
painter
.
restore
()
class
ComboBoxMenu
(
RoundMenu
):
...
...
@@ -231,13 +350,9 @@ class ComboBoxMenu(RoundMenu):
def
__init__
(
self
,
parent
=
None
):
super
().
__init__
(
title
=
""
,
parent
=
parent
)
self
.
view
.
setViewportMargins
(
5
,
2
,
5
,
6
)
self
.
view
.
setItemDelegate
(
ComboMenuItemDelegate
())
FluentStyleSheet
.
COMBO_BOX
.
apply
(
self
)
self
.
setItemHeight
(
33
)
def
addAction
(
self
,
action
):
super
().
addAction
(
action
)
item
=
self
.
view
.
item
(
self
.
view
.
count
()
-
1
)
w
=
ComboBoxMenuItemWidget
(
item
,
self
)
w
.
resize
(
item
.
sizeHint
())
self
.
view
.
setItemWidget
(
item
,
w
)
qfluentwidgets/components/widgets/info_bar.py
浏览文件 @
019b6612
...
...
@@ -78,8 +78,7 @@ class InfoIconWidget(QWidget):
if
self
.
icon
!=
InfoBarIcon
.
INFORMATION
:
drawIcon
(
self
.
icon
,
painter
,
self
.
rect
())
else
:
svg
=
writeSvg
(
self
.
icon
.
path
(),
[
0
],
fill
=
themeColor
().
name
())
drawSvgIcon
(
svg
.
encode
(),
painter
,
self
.
rect
())
drawIcon
(
self
.
icon
,
painter
,
self
.
rect
(),
indexes
=
[
0
],
fill
=
themeColor
().
name
())
class
InfoBar
(
QFrame
):
...
...
qfluentwidgets/components/widgets/line_edit.py
浏览文件 @
019b6612
...
...
@@ -5,7 +5,7 @@ from PyQt5.QtGui import QPainter, QPainterPath, QIcon
from
PyQt5.QtWidgets
import
QHBoxLayout
,
QLineEdit
,
QToolButton
,
QTextEdit
,
QPlainTextEdit
from
...common.style_sheet
import
FluentStyleSheet
,
themeColor
from
...common.icon
import
writeSvg
,
isDarkTheme
,
drawSvgIcon
,
FluentIconBase
from
...common.icon
import
isDarkTheme
,
FluentIconBase
,
drawIcon
from
...common.icon
import
FluentIcon
as
FIF
from
...common.smooth_scroll
import
SmoothMode
,
SmoothScroll
from
.menu
import
LineEditMenu
,
TextEditMenu
...
...
@@ -34,17 +34,16 @@ class LineEditButton(QToolButton):
rect
=
QRectF
((
w
-
iw
)
/
2
,
(
h
-
ih
)
/
2
,
iw
,
ih
)
if
isDarkTheme
():
self
.
_icon
.
render
(
painter
,
rect
)
drawIcon
(
self
.
_icon
,
painter
,
rect
)
else
:
svg
=
writeSvg
(
self
.
_icon
.
path
(),
fill
=
'#656565'
)
drawSvgIcon
(
svg
.
encode
(),
painter
,
rect
)
drawIcon
(
self
.
_icon
,
painter
,
rect
,
fill
=
'#656565'
)
class
LineEdit
(
QLineEdit
):
""" Line edit """
def
__init__
(
self
,
contents
=
''
,
parent
=
None
):
super
().
__init__
(
contents
,
parent
)
def
__init__
(
self
,
parent
=
None
):
super
().
__init__
(
parent
=
parent
)
self
.
_isClearButtonEnabled
=
False
FluentStyleSheet
.
LINE_EDIT
.
apply
(
self
)
...
...
@@ -117,7 +116,7 @@ class SearchLineEdit(LineEdit):
clearSignal
=
pyqtSignal
()
def
__init__
(
self
,
parent
=
None
):
super
().
__init__
(
''
,
parent
)
super
().
__init__
(
parent
)
self
.
searchButton
=
LineEditButton
(
FIF
.
SEARCH
,
self
)
self
.
hBoxLayout
.
addWidget
(
self
.
searchButton
,
0
,
Qt
.
AlignRight
)
...
...
qfluentwidgets/components/widgets/menu.py
浏览文件 @
019b6612
...
...
@@ -165,7 +165,7 @@ class MenuActionListWidget(QListWidget):
""" set the height of item """
for
i
in
range
(
self
.
count
()):
item
=
self
.
item
(
i
)
item
.
setSizeHint
(
item
.
sizeHint
().
width
(),
i
)
item
.
setSizeHint
(
item
.
sizeHint
().
width
(),
height
)
self
.
adjustSize
()
...
...
@@ -206,6 +206,7 @@ class RoundMenu(QWidget):
self
.
setShadowEffect
()
self
.
hBoxLayout
.
addWidget
(
self
.
view
,
1
,
Qt
.
AlignCenter
)
self
.
hBoxLayout
.
setSizeConstraint
(
QHBoxLayout
.
SetMinimumSize
)
self
.
hBoxLayout
.
setContentsMargins
(
12
,
8
,
12
,
20
)
FluentStyleSheet
.
MENU
.
apply
(
self
)
...
...
@@ -236,12 +237,6 @@ class RoundMenu(QWidget):
self
.
menuItem
=
item
self
.
isSubMenu
=
True
if
parent
else
False
def
adjustSize
(
self
):
m
=
self
.
layout
().
contentsMargins
()
w
=
self
.
view
.
width
()
+
m
.
left
()
+
m
.
right
()
h
=
self
.
view
.
height
()
+
m
.
top
()
+
m
.
bottom
()
self
.
setFixedSize
(
w
,
h
)
def
icon
(
self
):
return
self
.
_icon
...
...
setup.py
浏览文件 @
019b6612
...
...
@@ -6,7 +6,7 @@ with open('README.md', encoding='utf-8') as f:
setuptools
.
setup
(
name
=
"PyQt-Fluent-Widgets"
,
version
=
"0.6.
3
"
,
version
=
"0.6.
4
"
,
keywords
=
"pyqt fluent widgets"
,
author
=
"zhiyiYo"
,
author_email
=
"shokokawaii@outlook.com"
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录