ex4nicegui 0.7.0__py3-none-any.whl → 0.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ex4nicegui/reactive/EChartsComponent/ECharts.js +2 -3
- ex4nicegui/reactive/EChartsComponent/ECharts.py +2 -4
- ex4nicegui/reactive/__init__.py +6 -0
- ex4nicegui/reactive/base.py +3 -1
- ex4nicegui/reactive/mermaid/mermaid.py +2 -5
- ex4nicegui/reactive/mixins/backgroundColor.py +1 -1
- ex4nicegui/reactive/mixins/flexLayout.py +51 -0
- ex4nicegui/reactive/mixins/textColor.py +1 -1
- ex4nicegui/reactive/mixins/value_element.py +27 -0
- ex4nicegui/reactive/officials/avatar.py +86 -0
- ex4nicegui/reactive/officials/badge.py +102 -0
- ex4nicegui/reactive/officials/card.py +32 -2
- ex4nicegui/reactive/officials/checkbox.py +7 -12
- ex4nicegui/reactive/officials/chip.py +12 -3
- ex4nicegui/reactive/officials/circular_progress.py +7 -11
- ex4nicegui/reactive/officials/color_picker.py +4 -10
- ex4nicegui/reactive/officials/column.py +19 -11
- ex4nicegui/reactive/officials/date.py +4 -11
- ex4nicegui/reactive/officials/dialog.py +4 -11
- ex4nicegui/reactive/officials/echarts.py +10 -8
- ex4nicegui/reactive/officials/expansion.py +4 -11
- ex4nicegui/reactive/officials/icon.py +2 -8
- ex4nicegui/reactive/officials/image.py +1 -1
- ex4nicegui/reactive/officials/input.py +13 -14
- ex4nicegui/reactive/officials/knob.py +4 -13
- ex4nicegui/reactive/officials/label.py +6 -4
- ex4nicegui/reactive/officials/linear_progress.py +6 -11
- ex4nicegui/reactive/officials/number.py +8 -12
- ex4nicegui/reactive/officials/radio.py +5 -13
- ex4nicegui/reactive/officials/row.py +18 -11
- ex4nicegui/reactive/officials/select.py +2 -2
- ex4nicegui/reactive/officials/slider.py +4 -12
- ex4nicegui/reactive/officials/switch.py +5 -13
- ex4nicegui/reactive/officials/tab_panels.py +4 -8
- ex4nicegui/reactive/officials/tabs.py +4 -9
- ex4nicegui/reactive/officials/textarea.py +4 -10
- ex4nicegui/reactive/officials/toggle.py +88 -0
- ex4nicegui/reactive/officials/tooltip.py +1 -1
- ex4nicegui/reactive/systems/reactive_system.py +2 -2
- ex4nicegui/reactive/view_model.py +4 -4
- {ex4nicegui-0.7.0.dist-info → ex4nicegui-0.8.0.dist-info}/METADATA +157 -118
- {ex4nicegui-0.7.0.dist-info → ex4nicegui-0.8.0.dist-info}/RECORD +44 -39
- {ex4nicegui-0.7.0.dist-info → ex4nicegui-0.8.0.dist-info}/LICENSE +0 -0
- {ex4nicegui-0.7.0.dist-info → ex4nicegui-0.8.0.dist-info}/WHEEL +0 -0
|
@@ -2,14 +2,14 @@ from typing import Any, Callable, Optional
|
|
|
2
2
|
from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
|
|
3
3
|
from ex4nicegui.utils.signals import (
|
|
4
4
|
TGetterOrReadonlyRef,
|
|
5
|
-
to_value,
|
|
6
5
|
_TMaybeRef as TMaybeRef,
|
|
7
6
|
)
|
|
8
7
|
from nicegui import ui
|
|
9
8
|
from .base import BindableUi
|
|
9
|
+
from ex4nicegui.reactive.mixins.value_element import ValueElementMixin
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class TabsBindableUi(BindableUi[ui.tabs]):
|
|
12
|
+
class TabsBindableUi(BindableUi[ui.tabs], ValueElementMixin[str]):
|
|
13
13
|
def __init__(
|
|
14
14
|
self,
|
|
15
15
|
value: Optional[TMaybeRef[str]] = None,
|
|
@@ -33,12 +33,7 @@ class TabsBindableUi(BindableUi[ui.tabs]):
|
|
|
33
33
|
return self.element.value
|
|
34
34
|
|
|
35
35
|
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
36
|
-
if prop
|
|
37
|
-
return self
|
|
36
|
+
if ValueElementMixin._bind_specified_props(self, prop, value):
|
|
37
|
+
return self
|
|
38
38
|
|
|
39
39
|
return super().bind_prop(prop, value)
|
|
40
|
-
|
|
41
|
-
def bind_value(self, value: TGetterOrReadonlyRef):
|
|
42
|
-
@self._ui_effect
|
|
43
|
-
def _():
|
|
44
|
-
self.element.set_value(to_value(value))
|
|
@@ -16,9 +16,10 @@ from ex4nicegui.utils.signals import (
|
|
|
16
16
|
from nicegui import ui
|
|
17
17
|
from nicegui.events import handle_event
|
|
18
18
|
from .base import BindableUi
|
|
19
|
+
from ex4nicegui.reactive.mixins.value_element import ValueElementMixin
|
|
19
20
|
|
|
20
21
|
|
|
21
|
-
class TextareaBindableUi(BindableUi[ui.textarea]):
|
|
22
|
+
class TextareaBindableUi(BindableUi[ui.textarea], ValueElementMixin[str]):
|
|
22
23
|
def __init__(
|
|
23
24
|
self,
|
|
24
25
|
label: Optional[TMaybeRef[str]] = None,
|
|
@@ -53,18 +54,11 @@ class TextareaBindableUi(BindableUi[ui.textarea]):
|
|
|
53
54
|
return self.element.value
|
|
54
55
|
|
|
55
56
|
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
56
|
-
if prop
|
|
57
|
-
return self
|
|
57
|
+
if ValueElementMixin._bind_specified_props(self, prop, value):
|
|
58
|
+
return self
|
|
58
59
|
|
|
59
60
|
return super().bind_prop(prop, value)
|
|
60
61
|
|
|
61
|
-
def bind_value(self, value: TGetterOrReadonlyRef[str]):
|
|
62
|
-
@self._ui_effect
|
|
63
|
-
def _():
|
|
64
|
-
self.element.set_value(to_value(value))
|
|
65
|
-
|
|
66
|
-
return self
|
|
67
|
-
|
|
68
62
|
|
|
69
63
|
class LazyTextareaBindableUi(TextareaBindableUi):
|
|
70
64
|
def __init__(
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
from typing import (
|
|
2
|
+
Any,
|
|
3
|
+
Callable,
|
|
4
|
+
List,
|
|
5
|
+
Optional,
|
|
6
|
+
TypeVar,
|
|
7
|
+
Dict,
|
|
8
|
+
Union,
|
|
9
|
+
)
|
|
10
|
+
from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
|
|
11
|
+
from ex4nicegui.utils.signals import (
|
|
12
|
+
TGetterOrReadonlyRef,
|
|
13
|
+
_TMaybeRef as TMaybeRef,
|
|
14
|
+
to_value,
|
|
15
|
+
to_raw,
|
|
16
|
+
)
|
|
17
|
+
from nicegui import ui
|
|
18
|
+
from .base import BindableUi
|
|
19
|
+
|
|
20
|
+
T = TypeVar("T")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ToggleBindableUi(BindableUi[ui.toggle]):
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
options: Union[TMaybeRef[List], TMaybeRef[Dict]],
|
|
27
|
+
*,
|
|
28
|
+
value: TMaybeRef[Any] = None,
|
|
29
|
+
on_change: Optional[Callable[..., Any]] = None,
|
|
30
|
+
clearable: TMaybeRef[bool] = False,
|
|
31
|
+
) -> None:
|
|
32
|
+
"""Toggle
|
|
33
|
+
|
|
34
|
+
This element is based on Quasar's `QBtnToggle <https://quasar.dev/vue-components/button-toggle>`_ component.
|
|
35
|
+
|
|
36
|
+
The options can be specified as a list of values, or as a dictionary mapping values to labels.
|
|
37
|
+
After manipulating the options, call `update()` to update the options in the UI.
|
|
38
|
+
|
|
39
|
+
:param options: a list ['value1', ...] or dictionary `{'value1':'label1', ...}` specifying the options
|
|
40
|
+
:param value: the initial value
|
|
41
|
+
:param on_change: callback to execute when selection changes
|
|
42
|
+
:param clearable: whether the toggle can be cleared by clicking the selected option
|
|
43
|
+
"""
|
|
44
|
+
pc = ParameterClassifier(
|
|
45
|
+
locals(),
|
|
46
|
+
maybeRefs=[
|
|
47
|
+
"options",
|
|
48
|
+
"value",
|
|
49
|
+
"clearable",
|
|
50
|
+
],
|
|
51
|
+
v_model=("value", "on_change"),
|
|
52
|
+
events=["on_change"],
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
value_kws = pc.get_values_kws()
|
|
56
|
+
|
|
57
|
+
element = ui.toggle(**value_kws)
|
|
58
|
+
super().__init__(element) # type: ignore
|
|
59
|
+
|
|
60
|
+
for key, value in pc.get_bindings().items():
|
|
61
|
+
self.bind_prop(key, value) # type: ignore
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def value(self):
|
|
65
|
+
return self.element.value
|
|
66
|
+
|
|
67
|
+
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
68
|
+
if prop == "value":
|
|
69
|
+
return self.bind_value(value)
|
|
70
|
+
|
|
71
|
+
if prop == "options":
|
|
72
|
+
return self.bind_options(value)
|
|
73
|
+
|
|
74
|
+
return super().bind_prop(prop, value)
|
|
75
|
+
|
|
76
|
+
def bind_options(self, options: TGetterOrReadonlyRef):
|
|
77
|
+
@self._ui_signal_on(options, deep=True)
|
|
78
|
+
def _():
|
|
79
|
+
self.element.set_options(to_value(options))
|
|
80
|
+
|
|
81
|
+
return self
|
|
82
|
+
|
|
83
|
+
def bind_value(self, value: TGetterOrReadonlyRef):
|
|
84
|
+
@self._ui_signal_on(value, deep=True)
|
|
85
|
+
def _():
|
|
86
|
+
self.element.set_value(to_raw(to_value(value)) or None)
|
|
87
|
+
|
|
88
|
+
return self
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
from typing import Callable, Dict
|
|
2
|
-
from ex4nicegui.utils.signals import to_value
|
|
2
|
+
from ex4nicegui.utils.signals import to_value, to_raw
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
def convert_kws_ref2value(kws: Dict) -> Dict:
|
|
6
|
-
return {key: to_value(value) for key, value in kws.items()}
|
|
6
|
+
return {key: to_raw(to_value(value)) for key, value in kws.items()}
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def inject_method(obj, method_name: str, new_handle: Callable):
|
|
@@ -24,7 +24,7 @@ class ViewModel(NoProxy):
|
|
|
24
24
|
|
|
25
25
|
@see - https://github.com/CrystalWindSnake/ex4nicegui/blob/main/README.en.md#ViewModel
|
|
26
26
|
|
|
27
|
-
@中文文档 - https://gitee.com/carson_add/ex4nicegui/tree/main/#
|
|
27
|
+
@中文文档 - https://gitee.com/carson_add/ex4nicegui/tree/main/#viewmodel
|
|
28
28
|
|
|
29
29
|
Example:
|
|
30
30
|
.. code-block:: python
|
|
@@ -151,9 +151,9 @@ def cached_var(func: Callable[..., _T]) -> ReadonlyRef[_T]:
|
|
|
151
151
|
class MyVm(rxui.ViewModel):
|
|
152
152
|
name = rxui.var("John")
|
|
153
153
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
@rxui.cached_var
|
|
155
|
+
def uppper_name(self):
|
|
156
|
+
return self.name.value.upper()
|
|
157
157
|
|
|
158
158
|
"""
|
|
159
159
|
setattr(func, _CACHED_VARS_FLAG, None)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ex4nicegui
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: Extension library based on nicegui, providing data responsive,BI functionality modules
|
|
5
5
|
Home-page: https://github.com/CrystalWindSnake/ex4nicegui
|
|
6
6
|
License: MIT
|
|
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
18
|
Requires-Dist: executing (>=2.0.1,<3.0.0)
|
|
19
|
-
Requires-Dist: nicegui (>=
|
|
19
|
+
Requires-Dist: nicegui (>=2.0.0,<3.0.0)
|
|
20
20
|
Requires-Dist: signe (>=0.4.20,<0.5.0)
|
|
21
21
|
Project-URL: Repository, https://github.com/CrystalWindSnake/ex4nicegui
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
@@ -32,12 +32,16 @@ Description-Content-Type: text/markdown
|
|
|
32
32
|
- [教程](#教程)
|
|
33
33
|
- [安装](#-安装)
|
|
34
34
|
- [使用](#-使用)
|
|
35
|
-
- [
|
|
35
|
+
- [图表](#-图表)
|
|
36
36
|
- [BI 模块](#bi-模块)
|
|
37
37
|
|
|
38
38
|
对 [nicegui](https://github.com/zauberzeug/nicegui) 做的扩展库。内置响应式组件,完全实现数据响应式界面编程。
|
|
39
39
|
|
|
40
40
|
|
|
41
|
+

|
|
42
|
+
|
|
43
|
+
[查看更多示例](https://github.com/CrystalWindSnake/ex4nicegui-examples)
|
|
44
|
+
|
|
41
45
|
## 教程
|
|
42
46
|
[头条文章-秒杀官方实现,python界面库,去掉90%事件代码的nicegui](https://www.toutiao.com/item/7253786340574265860/)
|
|
43
47
|
|
|
@@ -59,10 +63,10 @@ pip install ex4nicegui -U
|
|
|
59
63
|
|
|
60
64
|
## 🦄 使用
|
|
61
65
|
|
|
66
|
+

|
|
62
67
|
```python
|
|
63
68
|
from nicegui import ui
|
|
64
|
-
from ex4nicegui import ref_computed, effect, to_ref
|
|
65
|
-
from ex4nicegui.reactive import rxui
|
|
69
|
+
from ex4nicegui import rxui, ref_computed, effect, to_ref
|
|
66
70
|
|
|
67
71
|
# 定义响应式数据
|
|
68
72
|
r_input = to_ref("")
|
|
@@ -73,127 +77,41 @@ rxui.label(r_input)
|
|
|
73
77
|
|
|
74
78
|
ui.run()
|
|
75
79
|
```
|
|
76
|
-

|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
### 提供 echarts 图表组件
|
|
80
|
-
|
|
81
|
-
```python
|
|
82
|
-
from nicegui import ui
|
|
83
|
-
from ex4nicegui import ref_computed, effect, to_ref
|
|
84
|
-
from ex4nicegui.reactive import rxui
|
|
85
|
-
|
|
86
|
-
r_input = to_ref("")
|
|
87
|
-
|
|
88
|
-
# ref_computed 创建只读响应式变量
|
|
89
|
-
# 函数中使用任意其他响应式变量,会自动关联
|
|
90
|
-
@ref_computed
|
|
91
|
-
def cp_echarts_opts():
|
|
92
|
-
return {
|
|
93
|
-
"title": {"text": r_input.value}, #字典中使用任意响应式变量,通过 .value 获取值
|
|
94
|
-
"xAxis": {
|
|
95
|
-
"type": "category",
|
|
96
|
-
"data": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
|
|
97
|
-
},
|
|
98
|
-
"yAxis": {"type": "value"},
|
|
99
|
-
"series": [
|
|
100
|
-
{
|
|
101
|
-
"data": [120, 200, 150, 80, 70, 110, 130],
|
|
102
|
-
"type": "bar",
|
|
103
|
-
"showBackground": True,
|
|
104
|
-
"backgroundStyle": {"color": "rgba(180, 180, 180, 0.2)"},
|
|
105
|
-
}
|
|
106
|
-
],
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
input = rxui.input("输入内容,图表标题会同步", value=r_input)
|
|
110
|
-
# 通过响应式组件对象的 element 属性,获取原生 nicegui 组件对象
|
|
111
|
-
input.element.classes("w-full")
|
|
112
|
-
|
|
113
|
-
rxui.echarts(cp_echarts_opts)
|
|
114
|
-
|
|
115
|
-
ui.run()
|
|
116
|
-
```
|
|
117
|
-

|
|
118
80
|
|
|
119
81
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
`on` 函数参数 `event_name` 以及 `query` 使用,查看[echarts 事件中文文档](https://echarts.apache.org/handbook/zh/concepts/event/)
|
|
82
|
+
---
|
|
123
83
|
|
|
84
|
+

|
|
124
85
|
|
|
125
|
-
以下例子绑定鼠标单击事件
|
|
126
86
|
```python
|
|
127
87
|
from nicegui import ui
|
|
128
|
-
from ex4nicegui
|
|
129
|
-
|
|
130
|
-
opts = {
|
|
131
|
-
"xAxis": {"type": "value", "boundaryGap": [0, 0.01]},
|
|
132
|
-
"yAxis": {
|
|
133
|
-
"type": "category",
|
|
134
|
-
"data": ["Brazil", "Indonesia", "USA", "India", "China", "World"],
|
|
135
|
-
},
|
|
136
|
-
"series": [
|
|
137
|
-
{
|
|
138
|
-
"name": "first",
|
|
139
|
-
"type": "bar",
|
|
140
|
-
"data": [18203, 23489, 29034, 104970, 131744, 630230],
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
"name": "second",
|
|
144
|
-
"type": "bar",
|
|
145
|
-
"data": [19325, 23438, 31000, 121594, 134141, 681807],
|
|
146
|
-
},
|
|
147
|
-
],
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
bar = rxui.echarts(opts)
|
|
151
|
-
|
|
152
|
-
def on_click(e: rxui.echarts.EChartsMouseEventArguments):
|
|
153
|
-
ui.notify(f"on_click:{e.seriesName}:{e.name}:{e.value}")
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
bar.on("click", on_click)
|
|
157
|
-
```
|
|
88
|
+
from ex4nicegui import rxui, to_ref
|
|
158
89
|
|
|
90
|
+
ui.radio.default_props("inline")
|
|
159
91
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
92
|
+
# 定义视图数据
|
|
93
|
+
colors = ["red", "green", "blue", "yellow", "purple", "white"]
|
|
94
|
+
color = to_ref("blue")
|
|
95
|
+
bg_color = to_ref("red")
|
|
164
96
|
|
|
165
|
-
opts = {
|
|
166
|
-
"xAxis": {"type": "value", "boundaryGap": [0, 0.01]},
|
|
167
|
-
"yAxis": {
|
|
168
|
-
"type": "category",
|
|
169
|
-
"data": ["Brazil", "Indonesia", "USA", "India", "China", "World"],
|
|
170
|
-
},
|
|
171
|
-
"series": [
|
|
172
|
-
{
|
|
173
|
-
"name": "first",
|
|
174
|
-
"type": "bar",
|
|
175
|
-
"data": [18203, 23489, 29034, 104970, 131744, 630230],
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
"name": "second",
|
|
179
|
-
"type": "bar",
|
|
180
|
-
"data": [19325, 23438, 31000, 121594, 134141, 681807],
|
|
181
|
-
},
|
|
182
|
-
],
|
|
183
|
-
}
|
|
184
97
|
|
|
185
|
-
|
|
98
|
+
## 函数中通过访问 `ref` 或其他关联函数获取值,一切会自动同步更新
|
|
99
|
+
def bg_text():
|
|
100
|
+
return f"Current background color is {bg_color.value}"
|
|
186
101
|
|
|
187
|
-
def on_first_series_mouseover(e: rxui.echarts.EChartsMouseEventArguments):
|
|
188
|
-
ui.notify(f"on_first_series_mouseover:{e.seriesName}:{e.name}:{e.value}")
|
|
189
102
|
|
|
103
|
+
# 界面
|
|
190
104
|
|
|
191
|
-
|
|
105
|
+
with ui.row(align_items="center"):
|
|
106
|
+
rxui.radio(colors, value=color)
|
|
107
|
+
## 可以使用 lambda
|
|
108
|
+
rxui.label(lambda: f"Font color is {color.value}").bind_style({"color": color})
|
|
192
109
|
|
|
193
|
-
ui.
|
|
110
|
+
with ui.row(align_items="center"):
|
|
111
|
+
rxui.radio(colors, value=bg_color)
|
|
112
|
+
## 直接绑定函数
|
|
113
|
+
rxui.label(bg_text).bind_style({"background-color": bg_color})
|
|
194
114
|
```
|
|
195
|
-
---
|
|
196
|
-
|
|
197
115
|
|
|
198
116
|
|
|
199
117
|
## ViewModel
|
|
@@ -264,19 +182,18 @@ class Home(rxui.ViewModel):
|
|
|
264
182
|
通过 `number` 组件修改年龄,一切都会自动更新。
|
|
265
183
|
|
|
266
184
|
```python
|
|
185
|
+
from typing import List
|
|
267
186
|
from ex4nicegui import rxui, Ref
|
|
268
187
|
from itertools import count
|
|
188
|
+
from nicegui import ui
|
|
269
189
|
|
|
270
190
|
id_generator = count()
|
|
271
191
|
|
|
272
192
|
class Person(rxui.ViewModel):
|
|
273
|
-
name
|
|
274
|
-
age = rxui.var(0)
|
|
275
|
-
|
|
276
|
-
def __init__(self, name: str = "", age: int = 0):
|
|
193
|
+
def __init__(self, name: str, age: int):
|
|
277
194
|
super().__init__()
|
|
278
|
-
self.name
|
|
279
|
-
self.age
|
|
195
|
+
self.name = rxui.var(name)
|
|
196
|
+
self.age = rxui.var(age)
|
|
280
197
|
self.id = next(id_generator)
|
|
281
198
|
|
|
282
199
|
|
|
@@ -318,6 +235,7 @@ with ui.row():
|
|
|
318
235
|
rxui.input(value=person.name, placeholder="名字")
|
|
319
236
|
rxui.number(value=person.age, min=1, max=100, step=1, placeholder="年龄")
|
|
320
237
|
|
|
238
|
+
ui.run()
|
|
321
239
|
```
|
|
322
240
|
|
|
323
241
|
如果你觉得 `rxui.vfor` 代码过于复杂,可以使用 `effect_refreshable` 装饰器代替。
|
|
@@ -326,7 +244,7 @@ with ui.row():
|
|
|
326
244
|
from ex4nicegui import rxui, Ref,effect_refreshable
|
|
327
245
|
...
|
|
328
246
|
|
|
329
|
-
# 明确指定监控 home.persons
|
|
247
|
+
# 明确指定监控 home.persons 变化,可以避免意外刷新
|
|
330
248
|
@effect_refreshable.on(home.persons)
|
|
331
249
|
def _():
|
|
332
250
|
|
|
@@ -343,6 +261,127 @@ def _():
|
|
|
343
261
|
|
|
344
262
|
---
|
|
345
263
|
|
|
264
|
+
## 图表
|
|
265
|
+
|
|
266
|
+
### 提供 echarts 图表组件
|
|
267
|
+
|
|
268
|
+
```python
|
|
269
|
+
from nicegui import ui
|
|
270
|
+
from ex4nicegui import ref_computed, effect, to_ref
|
|
271
|
+
from ex4nicegui.reactive import rxui
|
|
272
|
+
|
|
273
|
+
r_input = to_ref("")
|
|
274
|
+
|
|
275
|
+
# ref_computed 创建只读响应式变量
|
|
276
|
+
# 函数中使用任意其他响应式变量,会自动关联
|
|
277
|
+
@ref_computed
|
|
278
|
+
def cp_echarts_opts():
|
|
279
|
+
return {
|
|
280
|
+
"title": {"text": r_input.value}, #字典中使用任意响应式变量,通过 .value 获取值
|
|
281
|
+
"xAxis": {
|
|
282
|
+
"type": "category",
|
|
283
|
+
"data": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
|
|
284
|
+
},
|
|
285
|
+
"yAxis": {"type": "value"},
|
|
286
|
+
"series": [
|
|
287
|
+
{
|
|
288
|
+
"data": [120, 200, 150, 80, 70, 110, 130],
|
|
289
|
+
"type": "bar",
|
|
290
|
+
"showBackground": True,
|
|
291
|
+
"backgroundStyle": {"color": "rgba(180, 180, 180, 0.2)"},
|
|
292
|
+
}
|
|
293
|
+
],
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
input = rxui.input("输入内容,图表标题会同步", value=r_input)
|
|
297
|
+
# 通过响应式组件对象的 element 属性,获取原生 nicegui 组件对象
|
|
298
|
+
input.element.classes("w-full")
|
|
299
|
+
|
|
300
|
+
rxui.echarts(cp_echarts_opts)
|
|
301
|
+
|
|
302
|
+
ui.run()
|
|
303
|
+
```
|
|
304
|
+

|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
### echarts 图表鼠标事件
|
|
308
|
+
|
|
309
|
+
`on` 函数参数 `event_name` 以及 `query` 使用,查看[echarts 事件中文文档](https://echarts.apache.org/handbook/zh/concepts/event/)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
以下例子绑定鼠标单击事件
|
|
313
|
+
```python
|
|
314
|
+
from nicegui import ui
|
|
315
|
+
from ex4nicegui.reactive import rxui
|
|
316
|
+
|
|
317
|
+
opts = {
|
|
318
|
+
"xAxis": {"type": "value", "boundaryGap": [0, 0.01]},
|
|
319
|
+
"yAxis": {
|
|
320
|
+
"type": "category",
|
|
321
|
+
"data": ["Brazil", "Indonesia", "USA", "India", "China", "World"],
|
|
322
|
+
},
|
|
323
|
+
"series": [
|
|
324
|
+
{
|
|
325
|
+
"name": "first",
|
|
326
|
+
"type": "bar",
|
|
327
|
+
"data": [18203, 23489, 29034, 104970, 131744, 630230],
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
"name": "second",
|
|
331
|
+
"type": "bar",
|
|
332
|
+
"data": [19325, 23438, 31000, 121594, 134141, 681807],
|
|
333
|
+
},
|
|
334
|
+
],
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
bar = rxui.echarts(opts)
|
|
338
|
+
|
|
339
|
+
def on_click(e: rxui.echarts.EChartsMouseEventArguments):
|
|
340
|
+
ui.notify(f"on_click:{e.seriesName}:{e.name}:{e.value}")
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
bar.on("click", on_click)
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
以下例子只针对指定系列触发鼠标划过事件
|
|
348
|
+
```python
|
|
349
|
+
from nicegui import ui
|
|
350
|
+
from ex4nicegui.reactive import rxui
|
|
351
|
+
|
|
352
|
+
opts = {
|
|
353
|
+
"xAxis": {"type": "value", "boundaryGap": [0, 0.01]},
|
|
354
|
+
"yAxis": {
|
|
355
|
+
"type": "category",
|
|
356
|
+
"data": ["Brazil", "Indonesia", "USA", "India", "China", "World"],
|
|
357
|
+
},
|
|
358
|
+
"series": [
|
|
359
|
+
{
|
|
360
|
+
"name": "first",
|
|
361
|
+
"type": "bar",
|
|
362
|
+
"data": [18203, 23489, 29034, 104970, 131744, 630230],
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
"name": "second",
|
|
366
|
+
"type": "bar",
|
|
367
|
+
"data": [19325, 23438, 31000, 121594, 134141, 681807],
|
|
368
|
+
},
|
|
369
|
+
],
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
bar = rxui.echarts(opts)
|
|
373
|
+
|
|
374
|
+
def on_first_series_mouseover(e: rxui.echarts.EChartsMouseEventArguments):
|
|
375
|
+
ui.notify(f"on_first_series_mouseover:{e.seriesName}:{e.name}:{e.value}")
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
bar.on("mouseover", on_first_series_mouseover, query={"seriesName": "first"})
|
|
379
|
+
|
|
380
|
+
ui.run()
|
|
381
|
+
```
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
|
|
346
385
|
## 响应式
|
|
347
386
|
|
|
348
387
|
```python
|