Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
k54kdk
PyQt Fluent Widgets
提交
65b38311
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看板
提交
65b38311
编写于
4月 15, 2023
作者:
之一Yo
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
添加时间拾取器组件
上级
e8be9174
变更
20
展开全部
隐藏空白更改
内联
并排
Showing
20 changed file
with
51000 addition
and
50024 deletion
+51000
-50024
examples/gallery/app/view/status_info_interface.py
examples/gallery/app/view/status_info_interface.py
+1
-1
examples/time_picker/demo.py
examples/time_picker/demo.py
+40
-0
qfluentwidgets/_rc/images/icons/Accept_black.svg
qfluentwidgets/_rc/images/icons/Accept_black.svg
+4
-0
qfluentwidgets/_rc/images/icons/Accept_white.svg
qfluentwidgets/_rc/images/icons/Accept_white.svg
+4
-0
qfluentwidgets/_rc/images/time_picker/Down_black.svg
qfluentwidgets/_rc/images/time_picker/Down_black.svg
+4
-0
qfluentwidgets/_rc/images/time_picker/Down_white.svg
qfluentwidgets/_rc/images/time_picker/Down_white.svg
+4
-0
qfluentwidgets/_rc/images/time_picker/Up_black.svg
qfluentwidgets/_rc/images/time_picker/Up_black.svg
+4
-0
qfluentwidgets/_rc/images/time_picker/Up_white.svg
qfluentwidgets/_rc/images/time_picker/Up_white.svg
+4
-0
qfluentwidgets/_rc/qss/dark/time_picker.qss
qfluentwidgets/_rc/qss/dark/time_picker.qss
+102
-0
qfluentwidgets/_rc/qss/light/time_picker.qss
qfluentwidgets/_rc/qss/light/time_picker.qss
+101
-0
qfluentwidgets/_rc/resource.py
qfluentwidgets/_rc/resource.py
+49997
-50020
qfluentwidgets/_rc/resource.qrc
qfluentwidgets/_rc/resource.qrc
+8
-0
qfluentwidgets/common/icon.py
qfluentwidgets/common/icon.py
+1
-0
qfluentwidgets/common/style_sheet.py
qfluentwidgets/common/style_sheet.py
+1
-0
qfluentwidgets/components/__init__.py
qfluentwidgets/components/__init__.py
+2
-1
qfluentwidgets/components/date_time/__init__.py
qfluentwidgets/components/date_time/__init__.py
+2
-0
qfluentwidgets/components/date_time/picker_base.py
qfluentwidgets/components/date_time/picker_base.py
+370
-0
qfluentwidgets/components/date_time/time_picker.py
qfluentwidgets/components/date_time/time_picker.py
+109
-0
qfluentwidgets/components/widgets/__init__.py
qfluentwidgets/components/widgets/__init__.py
+3
-2
qfluentwidgets/components/widgets/cycle_list_widget.py
qfluentwidgets/components/widgets/cycle_list_widget.py
+239
-0
未找到文件。
examples/gallery/app/view/status_info_interface.py
浏览文件 @
65b38311
...
@@ -100,7 +100,7 @@ class StatusInfoInterface(GalleryInterface):
...
@@ -100,7 +100,7 @@ class StatusInfoInterface(GalleryInterface):
parent
=
self
parent
=
self
)
)
infoBar
.
addWidget
(
PushButton
(
self
.
tr
(
'Action'
)))
infoBar
.
addWidget
(
PushButton
(
self
.
tr
(
'Action'
)))
infoBar
.
setCustomBackgroundColor
(
"white"
,
"#2
02020
"
)
infoBar
.
setCustomBackgroundColor
(
"white"
,
"#2
a2a2a
"
)
self
.
addExampleCard
(
self
.
addExampleCard
(
self
.
tr
(
'An InfoBar with custom icon, background color and widget.'
),
self
.
tr
(
'An InfoBar with custom icon, background color and widget.'
),
infoBar
,
infoBar
,
...
...
examples/time_picker/demo.py
0 → 100644
浏览文件 @
65b38311
# coding:utf-8
import
sys
from
PyQt5.QtCore
import
Qt
,
QTime
from
PyQt5.QtWidgets
import
QApplication
from
PyQt5.QtWidgets
import
QApplication
,
QWidget
,
QVBoxLayout
from
qfluentwidgets
import
TimePicker
,
AMTimePicker
class
Demo
(
QWidget
):
def
__init__
(
self
):
super
().
__init__
()
self
.
vBoxLayout
=
QVBoxLayout
(
self
)
self
.
picker1
=
AMTimePicker
(
self
)
self
.
picker2
=
TimePicker
(
self
)
self
.
picker1
.
timeChanged
.
connect
(
lambda
t
:
print
(
t
.
toString
()))
self
.
picker2
.
timeChanged
.
connect
(
lambda
t
:
print
(
t
.
toString
()))
# set current time
# self.picker1.setTime(QTime(13, 15))
# self.picker2.setTime(QTime(13, 15))
self
.
resize
(
500
,
500
)
self
.
vBoxLayout
.
addWidget
(
self
.
picker1
,
0
,
Qt
.
AlignHCenter
)
self
.
vBoxLayout
.
addWidget
(
self
.
picker2
,
0
,
Qt
.
AlignHCenter
)
if
__name__
==
'__main__'
:
QApplication
.
setHighDpiScaleFactorRoundingPolicy
(
Qt
.
HighDpiScaleFactorRoundingPolicy
.
PassThrough
)
QApplication
.
setAttribute
(
Qt
.
AA_EnableHighDpiScaling
)
QApplication
.
setAttribute
(
Qt
.
AA_UseHighDpiPixmaps
)
app
=
QApplication
(
sys
.
argv
)
w
=
Demo
()
w
.
show
()
app
.
exec_
()
qfluentwidgets/_rc/images/icons/Accept_black.svg
0 → 100644
浏览文件 @
65b38311
<?xml version="1.0" encoding="utf-8"?>
<svg
id=
""
width=
"16"
height=
"16"
style=
"width:16px;height:16px;"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
viewBox=
"0 0 2048 2048"
enable-background=
"new 0 0 2048 2048"
xml:space=
"preserve"
><path
fill=
"#000000"
transform=
"translate(0, 350)"
d=
"M0 704 q0 -26 19 -45 q19 -19 45 -19 q26 0 45 19 l595 594 l1235 -1234 q19 -19 45 -19 q26 0 45 19 q19 19 19 45 q0 26 -19 45 l-1280 1280 q-19 19 -45 19 q-26 0 -45 -19 l-640 -640 q-19 -19 -19 -45 Z"
/></svg>
\ No newline at end of file
qfluentwidgets/_rc/images/icons/Accept_white.svg
0 → 100644
浏览文件 @
65b38311
<?xml version="1.0" encoding="utf-8"?>
<svg
id=
""
width=
"16"
height=
"16"
style=
"width:16px;height:16px;"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
viewBox=
"0 0 2048 2048"
enable-background=
"new 0 0 2048 2048"
xml:space=
"preserve"
><path
fill=
"#FFFFFF"
transform=
"translate(0, 350)"
d=
"M0 704 q0 -26 19 -45 q19 -19 45 -19 q26 0 45 19 l595 594 l1235 -1234 q19 -19 45 -19 q26 0 45 19 q19 19 19 45 q0 26 -19 45 l-1280 1280 q-19 19 -45 19 q-26 0 -45 -19 l-640 -640 q-19 -19 -19 -45 Z"
/></svg>
\ No newline at end of file
qfluentwidgets/_rc/images/time_picker/Down_black.svg
0 → 100644
浏览文件 @
65b38311
<?xml version="1.0" encoding="utf-8"?>
<svg
id=
""
width=
"16"
height=
"16"
style=
"width:16px;height:16px;"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
viewBox=
"0 0 2048 2048"
enable-background=
"new 0 0 2048 2048"
xml:space=
"preserve"
><path
fill=
"#5E5E5E"
transform=
"translate(0, 400)"
d=
"M0 184 q0 -37.71 13.71 -70.86 q13.71 -33.14 38.28 -58.29 q24.57 -25.15 57.14 -40 q32.57 -14.86 70.29 -14.86 l1689.14 0 q37.72 0 70.29 14.86 q32.57 14.86 57.14 40 q24.57 25.14 38.28 58.29 q13.72 33.14 13.72 70.86 q0 68.57 -44.57 120 l-790.86 924.57 q-36.57 42.29 -84.57 65.14 q-48 22.86 -104 22.86 q-56 0 -104 -22.86 q-48 -22.86 -84.57 -65.14 l-790.86 -924.57 q-44.57 -51.43 -44.57 -120 Z"
/></svg>
\ No newline at end of file
qfluentwidgets/_rc/images/time_picker/Down_white.svg
0 → 100644
浏览文件 @
65b38311
<?xml version="1.0" encoding="utf-8"?>
<svg
id=
""
width=
"16"
height=
"16"
style=
"width:16px;height:16px;"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
viewBox=
"0 0 2048 2048"
enable-background=
"new 0 0 2048 2048"
xml:space=
"preserve"
><path
fill=
"#FFFFFF"
transform=
"translate(0, 400)"
d=
"M0 184 q0 -37.71 13.71 -70.86 q13.71 -33.14 38.28 -58.29 q24.57 -25.15 57.14 -40 q32.57 -14.86 70.29 -14.86 l1689.14 0 q37.72 0 70.29 14.86 q32.57 14.86 57.14 40 q24.57 25.14 38.28 58.29 q13.72 33.14 13.72 70.86 q0 68.57 -44.57 120 l-790.86 924.57 q-36.57 42.29 -84.57 65.14 q-48 22.86 -104 22.86 q-56 0 -104 -22.86 q-48 -22.86 -84.57 -65.14 l-790.86 -924.57 q-44.57 -51.43 -44.57 -120 Z"
/></svg>
\ No newline at end of file
qfluentwidgets/_rc/images/time_picker/Up_black.svg
0 → 100644
浏览文件 @
65b38311
<?xml version="1.0" encoding="utf-8"?>
<svg
id=
""
width=
"16"
height=
"16"
style=
"width:16px;height:16px;"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
viewBox=
"0 0 2048 2048"
enable-background=
"new 0 0 2048 2048"
xml:space=
"preserve"
><path
fill=
"#5E5E5E"
transform=
"translate(0, 350)"
d=
"M179.43 1316.57 q-37.72 0 -70.29 -14.86 q-32.57 -14.86 -57.14 -40 q-24.57 -25.14 -38.28 -58.29 q-13.71 -33.14 -13.71 -70.86 q0 -68.57 44.57 -120 l790.86 -924.57 q36.57 -42.29 84.57 -65.14 q48 -22.86 104 -22.86 q113.14 0 188.57 88 l790.86 924.57 q44.57 51.43 44.57 120 q0 37.72 -13.72 70.86 q-13.71 33.14 -38.28 58.29 q-24.57 25.14 -57.14 40 q-32.57 14.86 -70.29 14.86 l-1689.14 0 Z"
/></svg>
\ No newline at end of file
qfluentwidgets/_rc/images/time_picker/Up_white.svg
0 → 100644
浏览文件 @
65b38311
<?xml version="1.0" encoding="utf-8"?>
<svg
id=
""
width=
"16"
height=
"16"
style=
"width:16px;height:16px;"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
viewBox=
"0 0 2048 2048"
enable-background=
"new 0 0 2048 2048"
xml:space=
"preserve"
><path
fill=
"#FFFFFF"
transform=
"translate(0, 350)"
d=
"M179.43 1316.57 q-37.72 0 -70.29 -14.86 q-32.57 -14.86 -57.14 -40 q-24.57 -25.14 -38.28 -58.29 q-13.71 -33.14 -13.71 -70.86 q0 -68.57 44.57 -120 l790.86 -924.57 q36.57 -42.29 84.57 -65.14 q48 -22.86 104 -22.86 q113.14 0 188.57 88 l790.86 924.57 q44.57 51.43 44.57 120 q0 37.72 -13.72 70.86 q-13.71 33.14 -38.28 58.29 q-24.57 25.14 -57.14 40 q-32.57 14.86 -70.29 14.86 l-1689.14 0 Z"
/></svg>
\ No newline at end of file
qfluentwidgets/_rc/qss/dark/time_picker.qss
0 → 100644
浏览文件 @
65b38311
ScrollButton {
background-color: rgb(44, 44, 44);
border: none;
border-radius: 7px;
}
CycleListWidget {
background-color: transparent;
border: none;
border-top-left-radius: 7px;
border-top-right-radius: 7px;
outline: none;
font: 14px 'Segoe UI', 'Microsoft YaHei';
}
CycleListWidget::item {
color: white;
background-color: transparent;
border: none;
border-radius: 5px;
margin: 0 4px;
padding-left: 11px;
padding-right: 11px;
}
CycleListWidget::item:hover {
background-color: rgba(255, 255, 255, 9);
}
CycleListWidget::item:selected {
background-color: rgba(255, 255, 255, 9);
}
CycleListWidget::item:selected:active {
background-color: rgba(255, 255, 255, 6);
}
PickerPanel > #view {
background-color: rgb(44, 44, 44);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 7px;
}
SeparatorWidget {
background-color: rgb(61, 61, 61);
}
ItemMaskWidget {
font: 14px 'Segoe UI', 'Microsoft YaHei';
}
PickerBase {
background: rgba(255, 255, 255, 0.0605);
border: 1px solid rgba(255, 255, 255, 0.053);
border-top: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 5px;
}
PickerBase:hover {
background: rgba(255, 255, 255, 0.0837);
}
PickerBase:pressed {
color: rgba(255, 255, 255, 0.786);
background: rgba(255, 255, 255, 0.0326);
border-top: 1px solid rgba(255, 255, 255, 0.053);
}
#pickerButton {
font: 14px 'Segoe UI', 'Microsoft YaHei';
color: rgba(255, 255, 255, 0.786);
background-color: transparent;
border: none;
outline: none;
}
#pickerButton[hasBorder=true] {
border-right: 1px solid rgba(255, 255, 255, 0.053);
}
#pickerButton[hasBorder=false] {
border-right: transparent;
}
#pickerButton[enter=true],
#pickerButton[hasValue=true] {
color: rgba(255, 255, 255, 1);
}
#pickerButton[pressed=true] {
color: rgba(255, 255, 255, 0.786);
}
#pickerButton[align="left"] {
text-align: left;
padding-left: 10px;
}
#pickerButton[align="right"] {
text-align: right;
padding-right: 10px;
}
\ No newline at end of file
qfluentwidgets/_rc/qss/light/time_picker.qss
0 → 100644
浏览文件 @
65b38311
ScrollButton {
background-color: rgb(249, 249, 249);
border: none;
border-radius: 7px;
}
CycleListWidget {
background-color: transparent;
border: none;
border-top-left-radius: 7px;
border-top-right-radius: 7px;
outline: none;
font: 14px 'Segoe UI', 'Microsoft YaHei';
}
CycleListWidget::item {
color: black;
background-color: transparent;
border: none;
border-radius: 5px;
margin: 0 4px;
padding-left: 11px;
padding-right: 11px;
}
CycleListWidget::item:hover {
background-color: rgba(0, 0, 0, 9);
}
CycleListWidget::item:selected {
background-color: rgba(0, 0, 0, 9);
}
CycleListWidget::item:selected:active {
background-color: rgba(0, 0, 0, 6);
}
PickerPanel > #view {
background-color: rgb(249, 249, 249);
border: 1px solid rgba(0, 0, 0, 0.14);
border-radius: 7px;
}
SeparatorWidget {
background-color: rgb(234, 234, 234);
}
ItemMaskWidget {
font: 14px 'Segoe UI', 'Microsoft YaHei';
}
PickerBase {
background: rgba(255, 255, 255, 0.7);
border: 1px solid rgba(0, 0, 0, 0.073);
border-bottom: 1px solid rgba(0, 0, 0, 0.183);
border-radius: 5px;
}
PickerBase:hover {
background: rgba(249, 249, 249, 0.5);
}
PickerBase:pressed {
background: rgba(249, 249, 249, 0.3);
border-bottom: 1px solid rgba(0, 0, 0, 0.073);
}
#pickerButton {
font: 14px 'Segoe UI', 'Microsoft YaHei';
color: rgba(0, 0, 0, 0.6);
background-color: transparent;
border: none;
outline: none;
}
#pickerButton[hasBorder=true] {
border-right: 1px solid rgba(0, 0, 0, 0.073);
}
#pickerButton[hasBorder=false] {
border-right: transparent;
}
#pickerButton[enter=true],
#pickerButton[hasValue=true] {
color: rgba(0, 0, 0, 0.896);
}
#pickerButton[pressed=true] {
color: rgba(0, 0, 0, 0.6);
}
#pickerButton[align="left"] {
text-align: left;
padding-left: 10px;
}
#pickerButton[align="right"] {
text-align: right;
padding-right: 10px;
}
qfluentwidgets/_rc/resource.py
浏览文件 @
65b38311
此差异已折叠。
点击以展开。
qfluentwidgets/_rc/resource.qrc
浏览文件 @
65b38311
...
@@ -159,6 +159,8 @@
...
@@ -159,6 +159,8 @@
<file>images/icons/Hide_white.svg</file>
<file>images/icons/Hide_white.svg</file>
<file>images/icons/Delete_black.svg</file>
<file>images/icons/Delete_black.svg</file>
<file>images/icons/Delete_white.svg</file>
<file>images/icons/Delete_white.svg</file>
<file>images/icons/Accept_black.svg</file>
<file>images/icons/Accept_white.svg</file>
<file>images/acrylic/noise.png</file>
<file>images/acrylic/noise.png</file>
<file>images/folder_list_dialog/Close_white.png</file>
<file>images/folder_list_dialog/Close_white.png</file>
<file>images/folder_list_dialog/Close_black.png</file>
<file>images/folder_list_dialog/Close_black.png</file>
...
@@ -184,6 +186,10 @@
...
@@ -184,6 +186,10 @@
<file>images/tree_view/TreeViewOpen_black.svg</file>
<file>images/tree_view/TreeViewOpen_black.svg</file>
<file>images/tree_view/TreeViewClose_white.svg</file>
<file>images/tree_view/TreeViewClose_white.svg</file>
<file>images/tree_view/TreeViewOpen_white.svg</file>
<file>images/tree_view/TreeViewOpen_white.svg</file>
<file>images/time_picker/Up_white.svg</file>
<file>images/time_picker/Up_black.svg</file>
<file>images/time_picker/Down_white.svg</file>
<file>images/time_picker/Down_black.svg</file>
<file>qss/dark/color_dialog.qss</file>
<file>qss/dark/color_dialog.qss</file>
<file>qss/dark/dialog.qss</file>
<file>qss/dark/dialog.qss</file>
...
@@ -205,6 +211,7 @@
...
@@ -205,6 +211,7 @@
<file>qss/dark/info_bar.qss</file>
<file>qss/dark/info_bar.qss</file>
<file>qss/dark/spin_box.qss</file>
<file>qss/dark/spin_box.qss</file>
<file>qss/dark/tree_view.qss</file>
<file>qss/dark/tree_view.qss</file>
<file>qss/dark/time_picker.qss</file>
<file>qss/light/color_dialog.qss</file>
<file>qss/light/color_dialog.qss</file>
<file>qss/light/dialog.qss</file>
<file>qss/light/dialog.qss</file>
...
@@ -226,5 +233,6 @@
...
@@ -226,5 +233,6 @@
<file>qss/light/info_bar.qss</file>
<file>qss/light/info_bar.qss</file>
<file>qss/light/spin_box.qss</file>
<file>qss/light/spin_box.qss</file>
<file>qss/light/tree_view.qss</file>
<file>qss/light/tree_view.qss</file>
<file>qss/light/time_picker.qss</file>
</qresource>
</qresource>
</RCC>
</RCC>
\ No newline at end of file
qfluentwidgets/common/icon.py
浏览文件 @
65b38311
...
@@ -240,6 +240,7 @@ class FluentIcon(FluentIconBase, Enum):
...
@@ -240,6 +240,7 @@ class FluentIcon(FluentIconBase, Enum):
SHARE
=
"Share"
SHARE
=
"Share"
UNPIN
=
"Unpin"
UNPIN
=
"Unpin"
VIDEO
=
"Video"
VIDEO
=
"Video"
ACCEPT
=
"Accept"
CAMERA
=
"Camera"
CAMERA
=
"Camera"
CANCEL
=
"Cancel"
CANCEL
=
"Cancel"
DELETE
=
"Delete"
DELETE
=
"Delete"
...
...
qfluentwidgets/common/style_sheet.py
浏览文件 @
65b38311
...
@@ -97,6 +97,7 @@ class FluentStyleSheet(StyleSheetBase, Enum):
...
@@ -97,6 +97,7 @@ class FluentStyleSheet(StyleSheetBase, Enum):
COMBO_BOX
=
"combo_box"
COMBO_BOX
=
"combo_box"
LINE_EDIT
=
"line_edit"
LINE_EDIT
=
"line_edit"
TREE_VIEW
=
"tree_view"
TREE_VIEW
=
"tree_view"
TIME_PICKER
=
"time_picker"
SETTING_CARD
=
"setting_card"
SETTING_CARD
=
"setting_card"
COLOR_DIALOG
=
"color_dialog"
COLOR_DIALOG
=
"color_dialog"
SWITCH_BUTTON
=
"switch_button"
SWITCH_BUTTON
=
"switch_button"
...
...
qfluentwidgets/components/__init__.py
浏览文件 @
65b38311
...
@@ -2,4 +2,5 @@ from .dialog_box import *
...
@@ -2,4 +2,5 @@ from .dialog_box import *
from
.layout
import
*
from
.layout
import
*
from
.settings
import
*
from
.settings
import
*
from
.widgets
import
*
from
.widgets
import
*
from
.navigation
import
*
from
.navigation
import
*
\ No newline at end of file
from
.date_time
import
*
\ No newline at end of file
qfluentwidgets/components/date_time/__init__.py
0 → 100644
浏览文件 @
65b38311
from
.time_picker
import
TimePicker
,
AMTimePicker
from
.picker_base
import
PickerBase
,
PickerPanel
\ No newline at end of file
qfluentwidgets/components/date_time/picker_base.py
0 → 100644
浏览文件 @
65b38311
# coding:utf-8
from
typing
import
Iterable
,
List
from
PyQt5.QtCore
import
QEvent
,
Qt
,
pyqtSignal
,
QSize
,
QRectF
,
QPoint
,
QPropertyAnimation
,
QEasingCurve
from
PyQt5.QtGui
import
QColor
,
QPainter
,
QCursor
,
QRegion
from
PyQt5.QtWidgets
import
(
QApplication
,
QWidget
,
QFrame
,
QVBoxLayout
,
QHBoxLayout
,
QGraphicsDropShadowEffect
,
QSizePolicy
,
QPushButton
,
QListWidgetItem
)
from
..widgets.cycle_list_widget
import
CycleListWidget
from
..widgets.button
import
TransparentToolButton
from
...common.icon
import
FluentIcon
from
...common.style_sheet
import
FluentStyleSheet
,
themeColor
,
isDarkTheme
class
SeparatorWidget
(
QWidget
):
""" Separator widget """
def
__init__
(
self
,
orient
:
Qt
.
Orientation
,
parent
=
None
):
super
().
__init__
(
parent
=
parent
)
if
orient
==
Qt
.
Horizontal
:
self
.
setFixedHeight
(
1
)
else
:
self
.
setFixedWidth
(
1
)
self
.
setAttribute
(
Qt
.
WA_StyledBackground
)
FluentStyleSheet
.
TIME_PICKER
.
apply
(
self
)
class
ItemMaskWidget
(
QWidget
):
""" Item mask widget """
def
__init__
(
self
,
listWidgets
:
List
[
CycleListWidget
],
parent
=
None
):
super
().
__init__
(
parent
=
parent
)
self
.
listWidgets
=
listWidgets
self
.
setFixedHeight
(
37
)
FluentStyleSheet
.
TIME_PICKER
.
apply
(
self
)
def
paintEvent
(
self
,
e
):
painter
=
QPainter
(
self
)
painter
.
setRenderHints
(
QPainter
.
Antialiasing
|
QPainter
.
TextAntialiasing
)
# draw background
painter
.
setPen
(
Qt
.
NoPen
)
painter
.
setBrush
(
themeColor
())
painter
.
drawRoundedRect
(
self
.
rect
().
adjusted
(
4
,
0
,
-
3
,
0
),
5
,
5
)
# draw text
painter
.
setPen
(
Qt
.
black
if
isDarkTheme
()
else
Qt
.
white
)
painter
.
setFont
(
self
.
font
())
w
,
h
=
0
,
self
.
height
()
for
i
,
p
in
enumerate
(
self
.
listWidgets
):
painter
.
save
()
# draw first item's text
x
=
p
.
itemSize
.
width
()
//
2
+
4
+
self
.
x
()
item1
=
p
.
itemAt
(
QPoint
(
x
,
self
.
y
()
+
6
))
if
not
item1
:
painter
.
restore
()
continue
iw
=
item1
.
sizeHint
().
width
()
y
=
p
.
visualItemRect
(
item1
).
y
()
painter
.
translate
(
w
,
y
-
self
.
y
()
+
7
)
self
.
_drawText
(
item1
,
painter
,
0
)
# draw second item's text
item2
=
p
.
itemAt
(
self
.
pos
()
+
QPoint
(
x
,
h
-
6
))
self
.
_drawText
(
item2
,
painter
,
h
)
painter
.
restore
()
w
+=
(
iw
+
8
)
# margin: 0 4px;
def
_drawText
(
self
,
item
:
QListWidgetItem
,
painter
:
QPainter
,
y
:
int
):
align
=
item
.
textAlignment
()
w
,
h
=
item
.
sizeHint
().
width
(),
item
.
sizeHint
().
height
()
if
align
&
Qt
.
AlignLeft
:
rect
=
QRectF
(
15
,
y
,
w
,
h
)
# padding-left: 11px
elif
align
&
Qt
.
AlignRight
:
rect
=
QRectF
(
4
,
y
,
w
-
15
,
h
)
# padding-right: 11px
elif
align
&
Qt
.
AlignCenter
:
rect
=
QRectF
(
4
,
y
,
w
,
h
)
painter
.
drawText
(
rect
,
align
,
item
.
text
())
class
PickerColumn
:
""" Picker column """
def
__init__
(
self
,
name
:
str
,
items
:
list
,
width
:
int
,
align
=
Qt
.
AlignLeft
):
self
.
name
=
name
self
.
items
=
items
self
.
width
=
width
self
.
align
=
align
self
.
value
=
None
# type: str
class
PickerBase
(
QPushButton
):
""" Picker base class """
def
__init__
(
self
,
parent
=
None
):
super
().
__init__
(
parent
=
parent
)
self
.
columns
=
[]
# type: List[PickerColumn]
self
.
columnMap
=
{}
self
.
buttons
=
[]
# type: List[QPushButton]
self
.
hBoxLayout
=
QHBoxLayout
(
self
)
self
.
hBoxLayout
.
setSpacing
(
0
)
self
.
hBoxLayout
.
setContentsMargins
(
0
,
0
,
0
,
0
)
self
.
hBoxLayout
.
setSizeConstraint
(
QHBoxLayout
.
SetFixedSize
)
FluentStyleSheet
.
TIME_PICKER
.
apply
(
self
)
self
.
clicked
.
connect
(
self
.
_showPanel
)
def
addColumn
(
self
,
name
:
str
,
items
:
Iterable
,
width
:
int
,
align
=
Qt
.
AlignCenter
):
""" add column
Parameters
----------
name: str
the name of column
items: Iterable
the items of column
width: int
the width of column
align: Qt.AlignmentFlag
the text alignment of button
"""
if
name
in
self
.
columnMap
:
return
# create column
column
=
PickerColumn
(
name
,
list
(
items
),
width
,
align
)
self
.
columns
.
append
(
column
)
self
.
columnMap
[
name
]
=
column
# create button
button
=
QPushButton
(
name
,
self
)
button
.
setFixedSize
(
width
,
30
)
button
.
setObjectName
(
'pickerButton'
)
button
.
setProperty
(
'hasBorder'
,
False
)
button
.
setAttribute
(
Qt
.
WA_TransparentForMouseEvents
)
self
.
hBoxLayout
.
addWidget
(
button
,
0
,
Qt
.
AlignLeft
)
self
.
buttons
.
append
(
button
)
if
align
==
Qt
.
AlignLeft
:
button
.
setProperty
(
'align'
,
'left'
)
elif
align
==
Qt
.
AlignRight
:
button
.
setProperty
(
'align'
,
'right'
)
# update the style of buttons
for
btn
in
self
.
buttons
[:
-
1
]:
btn
.
setProperty
(
'hasBorder'
,
True
)
btn
.
setStyle
(
QApplication
.
style
())
def
value
(
self
):
return
[
c
.
value
for
c
in
self
.
columns
]
def
setColumnValue
(
self
,
index
:
int
,
value
):
if
not
0
<=
index
<
len
(
self
.
columns
):
return
value
=
str
(
value
)
self
.
columns
[
index
].
value
=
value
self
.
buttons
[
index
].
setText
(
value
)
self
.
_setButtonProperty
(
'hasValue'
,
True
)
def
enterEvent
(
self
,
e
):
self
.
_setButtonProperty
(
'enter'
,
True
)
def
leaveEvent
(
self
,
e
):
self
.
_setButtonProperty
(
'enter'
,
False
)
def
mousePressEvent
(
self
,
e
):
self
.
_setButtonProperty
(
'pressed'
,
True
)
super
().
mousePressEvent
(
e
)
def
mouseReleaseEvent
(
self
,
e
):
self
.
_setButtonProperty
(
'pressed'
,
False
)
super
().
mouseReleaseEvent
(
e
)
def
_setButtonProperty
(
self
,
name
,
value
):
""" send event to picker buttons """
for
button
in
self
.
buttons
:
button
.
setProperty
(
name
,
value
)
button
.
setStyle
(
QApplication
.
style
())
def
_showPanel
(
self
):
""" show panel """
panel
=
PickerPanel
(
self
)
for
column
in
self
.
columns
:
panel
.
addColumn
(
column
.
items
,
column
.
width
,
column
.
align
)
panel
.
setValue
(
self
.
value
())
panel
.
confirmed
.
connect
(
self
.
_onConfirmed
)
panel
.
exec
(
self
.
mapToGlobal
(
QPoint
(
0
,
-
37
*
4
)))
def
_onConfirmed
(
self
,
value
:
list
):
for
i
,
v
in
enumerate
(
value
):
self
.
setColumnValue
(
i
,
v
)
class
PickerPanel
(
QWidget
):
""" picker panel """
confirmed
=
pyqtSignal
(
list
)
def
__init__
(
self
,
parent
=
None
):
super
().
__init__
(
parent
=
parent
)
self
.
itemHeight
=
37
self
.
listWidgets
=
[]
# type: List[CycleListWidget]
self
.
view
=
QFrame
(
self
)
self
.
itemMaskWidget
=
ItemMaskWidget
(
self
.
listWidgets
,
self
)
self
.
hSeparatorWidget
=
SeparatorWidget
(
Qt
.
Horizontal
,
self
.
view
)
self
.
yesButton
=
TransparentToolButton
(
FluentIcon
.
ACCEPT
,
self
.
view
)
self
.
cancelButton
=
TransparentToolButton
(
FluentIcon
.
CLOSE
,
self
.
view
)
self
.
hBoxLayout
=
QHBoxLayout
(
self
)
self
.
listLayout
=
QHBoxLayout
()
self
.
buttonLayout
=
QHBoxLayout
()
self
.
vBoxLayout
=
QVBoxLayout
(
self
.
view
)
self
.
__initWidget
()
def
__initWidget
(
self
):
self
.
setWindowFlags
(
Qt
.
Popup
|
Qt
.
FramelessWindowHint
|
Qt
.
NoDropShadowWindowHint
)
self
.
setAttribute
(
Qt
.
WA_TranslucentBackground
)
self
.
setShadowEffect
()
self
.
yesButton
.
setIconSize
(
QSize
(
16
,
16
))
self
.
cancelButton
.
setIconSize
(
QSize
(
13
,
13
))
self
.
yesButton
.
setFixedHeight
(
33
)
self
.
cancelButton
.
setFixedHeight
(
33
)
self
.
hBoxLayout
.
setContentsMargins
(
12
,
8
,
12
,
20
)
self
.
hBoxLayout
.
addWidget
(
self
.
view
,
1
,
Qt
.
AlignCenter
)
self
.
hBoxLayout
.
setSizeConstraint
(
QHBoxLayout
.
SetMinimumSize
)
self
.
vBoxLayout
.
setSpacing
(
0
)
self
.
vBoxLayout
.
setContentsMargins
(
0
,
0
,
0
,
0
)
self
.
vBoxLayout
.
addLayout
(
self
.
listLayout
,
1
)
self
.
vBoxLayout
.
addWidget
(
self
.
hSeparatorWidget
)
self
.
vBoxLayout
.
addLayout
(
self
.
buttonLayout
,
1
)
self
.
vBoxLayout
.
setSizeConstraint
(
QVBoxLayout
.
SetMinimumSize
)
self
.
buttonLayout
.
setSpacing
(
6
)
self
.
buttonLayout
.
setContentsMargins
(
3
,
3
,
3
,
3
)
self
.
buttonLayout
.
addWidget
(
self
.
yesButton
)
self
.
buttonLayout
.
addWidget
(
self
.
cancelButton
)
self
.
yesButton
.
setSizePolicy
(
QSizePolicy
.
Expanding
,
QSizePolicy
.
Expanding
)
self
.
cancelButton
.
setSizePolicy
(
QSizePolicy
.
Expanding
,
QSizePolicy
.
Expanding
)
self
.
yesButton
.
clicked
.
connect
(
self
.
_fadeOut
)
self
.
yesButton
.
clicked
.
connect
(
lambda
:
self
.
confirmed
.
emit
(
self
.
value
()))
self
.
cancelButton
.
clicked
.
connect
(
self
.
_fadeOut
)
self
.
view
.
setObjectName
(
'view'
)
FluentStyleSheet
.
TIME_PICKER
.
apply
(
self
)
def
setShadowEffect
(
self
,
blurRadius
=
30
,
offset
=
(
0
,
8
),
color
=
QColor
(
0
,
0
,
0
,
30
)):
""" add shadow to dialog """
self
.
shadowEffect
=
QGraphicsDropShadowEffect
(
self
.
view
)
self
.
shadowEffect
.
setBlurRadius
(
blurRadius
)
self
.
shadowEffect
.
setOffset
(
*
offset
)
self
.
shadowEffect
.
setColor
(
color
)
self
.
view
.
setGraphicsEffect
(
None
)
self
.
view
.
setGraphicsEffect
(
self
.
shadowEffect
)
def
addColumn
(
self
,
items
:
Iterable
,
width
:
int
,
align
=
Qt
.
AlignCenter
):
""" add one column to view
Parameters
----------
items: Iterable[Any]
the items to be added
width: int
the width of item
align: Qt.AlignmentFlag
the text alignment of item
"""
if
self
.
listWidgets
:
self
.
listLayout
.
addWidget
(
SeparatorWidget
(
Qt
.
Vertical
))
w
=
CycleListWidget
(
items
,
QSize
(
width
,
self
.
itemHeight
),
align
,
self
)
w
.
vScrollBar
.
valueChanged
.
connect
(
self
.
itemMaskWidget
.
update
)
self
.
listWidgets
.
append
(
w
)
self
.
listLayout
.
addWidget
(
w
)
def
resizeEvent
(
self
,
e
):
self
.
itemMaskWidget
.
resize
(
self
.
view
.
width
()
-
3
,
self
.
itemHeight
)
m
=
self
.
hBoxLayout
.
contentsMargins
()
self
.
itemMaskWidget
.
move
(
m
.
left
()
+
2
,
m
.
top
()
+
148
)
def
value
(
self
):
return
[
i
.
currentItem
().
text
()
for
i
in
self
.
listWidgets
]
def
setValue
(
self
,
value
:
list
):
for
v
,
w
in
zip
(
value
,
self
.
listWidgets
):
w
.
setSelectedItem
(
v
)
def
exec
(
self
,
pos
,
ani
=
True
):
""" show menu
Parameters
----------
pos: QPoint
pop-up position
ani: bool
Whether to show pop-up animation
"""
if
self
.
isVisible
():
return
rect
=
QApplication
.
screenAt
(
QCursor
.
pos
()).
availableGeometry
()
w
,
h
=
self
.
width
()
+
5
,
self
.
height
()
+
5
pos
.
setX
(
min
(
pos
.
x
()
-
self
.
layout
().
contentsMargins
().
left
(),
rect
.
right
()
-
w
))
pos
.
setY
(
max
(
rect
.
top
(),
min
(
pos
.
y
()
-
4
,
rect
.
bottom
()
-
h
)))
self
.
move
(
pos
)
# show before running animation, or the height calculation will be wrong
self
.
show
()
if
not
ani
:
return
self
.
isExpanded
=
False
self
.
ani
=
QPropertyAnimation
(
self
.
view
,
b
'windowOpacity'
,
self
)
self
.
ani
.
valueChanged
.
connect
(
self
.
_onAniValueChanged
)
self
.
ani
.
setStartValue
(
0
)
self
.
ani
.
setEndValue
(
1
)
self
.
ani
.
setDuration
(
150
)
self
.
ani
.
setEasingCurve
(
QEasingCurve
.
OutQuad
)
self
.
ani
.
start
()
def
_onAniValueChanged
(
self
,
opacity
):
m
=
self
.
layout
().
contentsMargins
()
w
=
self
.
view
.
width
()
+
m
.
left
()
+
m
.
right
()
+
120
h
=
self
.
view
.
height
()
+
m
.
top
()
+
m
.
bottom
()
+
12
if
not
self
.
isExpanded
:
y
=
int
(
h
/
2
*
(
1
-
opacity
))
self
.
setMask
(
QRegion
(
0
,
y
,
w
,
h
-
y
*
2
))
else
:
y
=
int
(
h
/
3
*
(
1
-
opacity
))
self
.
setMask
(
QRegion
(
0
,
y
,
w
,
h
-
y
*
2
))
def
_fadeOut
(
self
):
self
.
isExpanded
=
True
self
.
ani
=
QPropertyAnimation
(
self
,
b
'windowOpacity'
,
self
)
self
.
ani
.
valueChanged
.
connect
(
self
.
_onAniValueChanged
)
self
.
ani
.
finished
.
connect
(
self
.
deleteLater
)
self
.
ani
.
setStartValue
(
1
)
self
.
ani
.
setEndValue
(
0
)
self
.
ani
.
setDuration
(
150
)
self
.
ani
.
setEasingCurve
(
QEasingCurve
.
OutQuad
)
self
.
ani
.
start
()
qfluentwidgets/components/date_time/time_picker.py
0 → 100644
浏览文件 @
65b38311
# coding:utf-8
from
enum
import
Enum
from
PyQt5.QtCore
import
Qt
,
pyqtSignal
,
QSize
,
QTime
from
PyQt5.QtGui
import
QPixmap
from
PyQt5.QtWidgets
import
QWidget
from
.picker_base
import
PickerBase
class
TimePickerBase
(
PickerBase
):
""" Time picker base class """
timeChanged
=
pyqtSignal
(
QTime
)
def
__init__
(
self
,
parent
=
None
):
super
().
__init__
(
parent
=
parent
)
self
.
time
=
QTime
()
self
.
_addColumns
()
def
_addColumns
(
self
):
""" add column to time picker """
raise
NotImplementedError
def
setTime
(
self
,
time
:
QTime
):
""" set current time
Parameters
----------
time: QTime
current time
"""
raise
NotImplementedError
class
TimePicker
(
TimePickerBase
):
""" 24 hours time picker """
def
_addColumns
(
self
):
self
.
addColumn
(
self
.
tr
(
'hour'
),
range
(
0
,
24
),
120
)
minute
=
[
str
(
i
).
zfill
(
2
)
for
i
in
range
(
0
,
60
)]
self
.
addColumn
(
self
.
tr
(
'minute'
),
minute
,
120
)
def
setTime
(
self
,
time
):
if
not
time
.
isValid
()
or
time
.
isNull
():
return
self
.
time
=
time
self
.
setColumnValue
(
0
,
time
.
hour
())
self
.
setColumnValue
(
1
,
str
(
time
.
minute
()).
zfill
(
2
))
def
_onConfirmed
(
self
,
value
:
list
):
super
().
_onConfirmed
(
value
)
h
,
m
=
int
(
value
[
0
]),
int
(
value
[
1
])
time
=
QTime
(
h
,
m
)
ot
=
self
.
time
self
.
setTime
(
time
)
if
ot
!=
time
:
self
.
timeChanged
.
emit
(
time
)
class
AMTimePicker
(
TimePickerBase
):
""" AM/PM time picker """
def
__init__
(
self
,
parent
=
None
):
super
().
__init__
(
parent
)
def
_addColumns
(
self
):
self
.
addColumn
(
self
.
tr
(
'hour'
),
range
(
1
,
13
),
80
)
minute
=
[
str
(
i
).
zfill
(
2
)
for
i
in
range
(
0
,
60
)]
self
.
addColumn
(
self
.
tr
(
'minute'
),
minute
,
80
)
self
.
addColumn
(
self
.
tr
(
'AM'
),
[
self
.
tr
(
'AM'
),
self
.
tr
(
'PM'
)],
80
)
def
setTime
(
self
,
time
):
if
not
time
.
isValid
()
or
time
.
isNull
():
return
self
.
time
=
time
h
=
time
.
hour
()
if
h
in
[
0
,
12
]:
self
.
setColumnValue
(
0
,
12
)
else
:
self
.
setColumnValue
(
0
,
h
%
12
)
self
.
setColumnValue
(
1
,
str
(
time
.
minute
()).
zfill
(
2
))
self
.
setColumnValue
(
2
,
self
.
tr
(
'AM'
)
if
h
<
12
else
self
.
tr
(
'PM'
))
def
_onConfirmed
(
self
,
value
:
list
):
super
().
_onConfirmed
(
value
)
h
,
m
,
p
=
value
h
,
m
=
int
(
h
),
int
(
m
)
if
p
==
self
.
tr
(
'AM'
):
h
=
0
if
h
==
12
else
h
elif
p
==
self
.
tr
(
'PM'
):
h
=
h
if
h
==
12
else
h
+
12
time
=
QTime
(
h
,
m
)
ot
=
self
.
time
self
.
setTime
(
time
)
if
ot
!=
time
:
self
.
timeChanged
.
emit
(
time
)
qfluentwidgets/components/widgets/__init__.py
浏览文件 @
65b38311
from
.button
import
PrimaryPushButton
,
PushButton
,
RadioButton
,
HyperlinkButton
,
ToolButton
from
.button
import
PrimaryPushButton
,
PushButton
,
RadioButton
,
HyperlinkButton
,
ToolButton
,
TransparentToolButton
from
.check_box
import
CheckBox
from
.check_box
import
CheckBox
from
.combo_box
import
ComboBox
,
EditableComboBox
from
.combo_box
import
ComboBox
,
EditableComboBox
from
.line_edit
import
LineEdit
,
TextEdit
,
PlainTextEdit
,
LineEditButton
,
SearchLineEdit
from
.line_edit
import
LineEdit
,
TextEdit
,
PlainTextEdit
,
LineEditButton
,
SearchLineEdit
...
@@ -13,4 +13,5 @@ from .stacked_widget import PopUpAniStackedWidget, OpacityAniStackedWidget
...
@@ -13,4 +13,5 @@ from .stacked_widget import PopUpAniStackedWidget, OpacityAniStackedWidget
from
.state_tool_tip
import
StateToolTip
from
.state_tool_tip
import
StateToolTip
from
.switch_button
import
SwitchButton
,
IndicatorPosition
from
.switch_button
import
SwitchButton
,
IndicatorPosition
from
.tool_tip
import
ToolTip
,
ToolTipFilter
from
.tool_tip
import
ToolTip
,
ToolTipFilter
from
.tree_view
import
TreeWidget
,
TreeView
from
.tree_view
import
TreeWidget
,
TreeView
\ No newline at end of file
from
.cycle_list_widget
import
CycleListWidget
\ No newline at end of file
qfluentwidgets/components/widgets/cycle_list_widget.py
0 → 100644
浏览文件 @
65b38311
# coding:utf-8
from
enum
import
Enum
from
typing
import
Iterable
from
PyQt5.QtCore
import
Qt
,
pyqtSignal
,
QSize
,
QEvent
,
QRectF
,
QPoint
from
PyQt5.QtGui
import
QPainter
from
PyQt5.QtWidgets
import
QWidget
,
QListWidget
,
QListWidgetItem
,
QToolButton
,
QStyledItemDelegate
from
.scroll_area
import
SmoothScrollBar
from
...common.icon
import
FluentIconBase
,
Theme
,
getIconColor
from
...common.style_sheet
import
themeColor
,
isDarkTheme
class
ScrollIcon
(
FluentIconBase
,
Enum
):
""" Scroll icon """
UP
=
"Up"
DOWN
=
"Down"
def
path
(
self
,
theme
=
Theme
.
AUTO
):
if
theme
==
Theme
.
AUTO
:
c
=
getIconColor
()
else
:
c
=
"white"
if
theme
==
Theme
.
DARK
else
"black"
return
f
':/qfluentwidgets/images/time_picker/
{
self
.
value
}
_
{
c
}
.svg'
class
ScrollButton
(
QToolButton
):
""" Scroll button """
def
__init__
(
self
,
icon
:
ScrollIcon
,
parent
=
None
):
super
().
__init__
(
parent
=
parent
)
self
.
_icon
=
icon
self
.
isPressed
=
False
self
.
installEventFilter
(
self
)
def
eventFilter
(
self
,
obj
,
e
:
QEvent
):
if
obj
is
self
:
if
e
.
type
()
==
QEvent
.
MouseButtonPress
:
self
.
isPressed
=
True
self
.
update
()
elif
e
.
type
()
==
QEvent
.
MouseButtonRelease
:
self
.
isPressed
=
False
self
.
update
()
return
super
().
eventFilter
(
obj
,
e
)
def
paintEvent
(
self
,
e
):
super
().
paintEvent
(
e
)
painter
=
QPainter
(
self
)
painter
.
setRenderHints
(
QPainter
.
Antialiasing
)
if
not
self
.
isPressed
:
w
,
h
=
10
,
10
else
:
w
,
h
=
8
,
8
x
=
(
self
.
width
()
-
w
)
/
2
y
=
(
self
.
height
()
-
h
)
/
2
self
.
_icon
.
render
(
painter
,
QRectF
(
x
,
y
,
w
,
h
))
class
CycleListWidget
(
QListWidget
):
""" Cycle list widget """
def
__init__
(
self
,
items
:
Iterable
,
itemSize
:
QSize
,
align
=
Qt
.
AlignCenter
,
parent
=
None
):
"""
Parameters
----------
items: Iterable[Any]
the items to be added
itemSize: QSize
the size of item
align: Qt.AlignmentFlag
the text alignment of item
parent: QWidget
parent widget
"""
super
().
__init__
(
parent
=
parent
)
self
.
itemSize
=
itemSize
self
.
upButton
=
ScrollButton
(
ScrollIcon
.
UP
,
self
)
self
.
downButton
=
ScrollButton
(
ScrollIcon
.
DOWN
,
self
)
self
.
scrollDuration
=
250
self
.
originItems
=
list
(
items
)
self
.
vScrollBar
=
SmoothScrollBar
(
self
)
self
.
visibleNumber
=
9
# repeat adding items to achieve circular scrolling
self
.
_createItems
(
items
,
itemSize
,
align
)
self
.
setVerticalScrollMode
(
self
.
ScrollPerPixel
)
self
.
setVerticalScrollBar
(
self
.
vScrollBar
)
self
.
vScrollBar
.
setScrollAnimation
(
self
.
scrollDuration
)
self
.
setViewportMargins
(
0
,
0
,
0
,
0
)
self
.
setFixedSize
(
itemSize
.
width
()
+
8
,
itemSize
.
height
()
*
self
.
visibleNumber
)
# hide scroll bar
self
.
setHorizontalScrollBarPolicy
(
Qt
.
ScrollBarAlwaysOff
)
self
.
setVerticalScrollBarPolicy
(
Qt
.
ScrollBarAlwaysOff
)
self
.
upButton
.
hide
()
self
.
downButton
.
hide
()
self
.
upButton
.
clicked
.
connect
(
self
.
scrollUp
)
self
.
downButton
.
clicked
.
connect
(
self
.
scrollDown
)
self
.
itemClicked
.
connect
(
self
.
_onItemClicked
)
self
.
installEventFilter
(
self
)
def
_createItems
(
self
,
items
:
list
,
itemSize
:
QSize
,
align
=
Qt
.
AlignCenter
):
N
=
len
(
items
)
self
.
isCycle
=
N
>
self
.
visibleNumber
if
self
.
isCycle
:
for
_
in
range
(
2
):
self
.
_addColumnItems
(
items
,
itemSize
,
align
)
self
.
_currentIndex
=
len
(
items
)
super
().
scrollToItem
(
self
.
item
(
self
.
currentIndex
()
-
self
.
visibleNumber
//
2
),
QListWidget
.
PositionAtTop
)
else
:
n
=
self
.
visibleNumber
//
2
# add empty items to enable scrolling
self
.
_addColumnItems
([
''
]
*
n
,
itemSize
,
align
,
True
)
self
.
_addColumnItems
(
items
,
itemSize
,
align
)
self
.
_addColumnItems
([
''
]
*
n
,
itemSize
,
align
,
True
)
self
.
_currentIndex
=
n
def
_addColumnItems
(
self
,
items
,
itemSize
,
align
,
disabled
=
False
):
for
i
in
items
:
item
=
QListWidgetItem
(
str
(
i
),
self
)
item
.
setSizeHint
(
itemSize
)
item
.
setTextAlignment
(
align
|
Qt
.
AlignVCenter
)
if
disabled
:
item
.
setFlags
(
Qt
.
NoItemFlags
)
self
.
addItem
(
item
)
def
_onItemClicked
(
self
,
item
):
self
.
setCurrentIndex
(
self
.
row
(
item
))
self
.
scrollToItem
(
self
.
currentItem
())
def
setSelectedItem
(
self
,
text
:
str
):
""" set the selected item """
if
text
is
None
:
return
items
=
self
.
findItems
(
str
(
text
),
Qt
.
MatchExactly
)
if
not
items
:
return
if
len
(
items
)
>=
2
:
self
.
setCurrentIndex
(
self
.
row
(
items
[
1
]))
else
:
self
.
setCurrentIndex
(
self
.
row
(
items
[
0
]))
super
().
scrollToItem
(
self
.
currentItem
(),
QListWidget
.
PositionAtCenter
)
def
scrollToItem
(
self
,
item
:
QListWidgetItem
,
hint
=
QListWidget
.
PositionAtCenter
):
""" scroll to item """
# scroll to center position
index
=
self
.
row
(
item
)
y
=
item
.
sizeHint
().
height
()
*
(
index
-
self
.
visibleNumber
//
2
)
self
.
vScrollBar
.
scrollTo
(
y
)
# clear selection
self
.
clearSelection
()
item
.
setSelected
(
False
)
def
wheelEvent
(
self
,
e
):
if
e
.
angleDelta
().
y
()
<
0
:
self
.
scrollDown
()
else
:
self
.
scrollUp
()
def
scrollDown
(
self
):
""" scroll down an item """
self
.
setCurrentIndex
(
self
.
currentIndex
()
+
1
)
self
.
scrollToItem
(
self
.
currentItem
())
def
scrollUp
(
self
):
""" scroll up an item """
self
.
setCurrentIndex
(
self
.
currentIndex
()
-
1
)
self
.
scrollToItem
(
self
.
currentItem
())
def
enterEvent
(
self
,
e
):
self
.
upButton
.
show
()
self
.
downButton
.
show
()
def
leaveEvent
(
self
,
e
):
self
.
upButton
.
hide
()
self
.
downButton
.
hide
()
def
resizeEvent
(
self
,
e
):
self
.
upButton
.
resize
(
self
.
width
(),
34
)
self
.
downButton
.
resize
(
self
.
width
(),
34
)
self
.
downButton
.
move
(
0
,
self
.
height
()
-
34
)
def
eventFilter
(
self
,
obj
,
e
:
QEvent
):
if
obj
is
not
self
or
e
.
type
()
!=
QEvent
.
KeyPress
:
return
super
().
eventFilter
(
obj
,
e
)
if
e
.
key
()
==
Qt
.
Key_Down
:
self
.
scrollDown
()
return
True
elif
e
.
key
()
==
Qt
.
Key_Up
:
self
.
scrollUp
()
return
True
return
super
().
eventFilter
(
obj
,
e
)
def
currentItem
(
self
):
return
self
.
item
(
self
.
currentIndex
())
def
currentIndex
(
self
):
return
self
.
_currentIndex
def
setCurrentIndex
(
self
,
index
:
int
):
if
not
self
.
isCycle
:
n
=
self
.
visibleNumber
//
2
self
.
_currentIndex
=
max
(
n
,
min
(
n
+
len
(
self
.
originItems
)
-
1
,
index
))
else
:
N
=
self
.
count
()
//
2
m
=
(
self
.
visibleNumber
+
1
)
//
2
self
.
_currentIndex
=
index
# scroll to center to achieve circular scrolling
if
index
>=
self
.
count
()
-
m
:
self
.
_currentIndex
=
N
+
index
-
self
.
count
()
super
().
scrollToItem
(
self
.
item
(
self
.
currentIndex
()
-
1
),
self
.
PositionAtCenter
)
elif
index
<=
m
-
1
:
self
.
_currentIndex
=
N
+
index
super
().
scrollToItem
(
self
.
item
(
N
+
index
+
1
),
self
.
PositionAtCenter
)
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录