Skip to content

Commit 6b84074

Browse files
v1: Charts and routing examples (#5764)
* Add declarative dashboard example with line charts Introduces a new example for a dashboard using Flet and Flet Charts, displaying CPU, memory, and disk usage as animated line charts. Demonstrates component-based design and real-time data updates for chart visualization. * Refactor routing-navigation examples for async routes Updated routing-navigation example apps to use async route handling and push_route instead of go for navigation. Improved view management and event handling, and replaced flet.app with flet.run for app startup. Removed requirements.txt as dependencies are now managed elsewhere. * Refactor route change handling in navigation examples Moved and updated route_change and view_pop logic in routing-navigation examples for consistency and clarity. Improved example in Page control documentation to use ft.Button, update views, and clarify async usage. * Add contributing guide to Python package docs Added a reference to the main CONTRIBUTING.md file in the Python package documentation to provide contribution guidelines for developers. Close #5769 * Add divider_color support to theme configuration Introduces the divider_color property to the Theme class in Python and updates Dart theme parsing to use divider_color from the theme configuration. This allows customization of divider colors in UI components such as Divider, VerticalDivider, ListTile, and DataTable. * Fix documentation links and animation curve reference Corrected the example_media path in Switch control docs and updated references in ExpansionTile docstrings to use the correct link format and AnimationCurve.EASE_IN instead of Curves.EASE_IN. * Improve type annotations and docstrings in hooks and controls Updated docstrings in use_effect.py to clarify argument types and descriptions for hook functions. Improved type annotation for dataclass_kwargs in base_control.py to specify Any type for keyword arguments. * Update badge property handling in pie chart section Introduces 'skip_properties' for 'badge' in PieChartSection Python class and updates Dart code to use 'badge' instead of 'badge_content' for widget building. This improves consistency and property management between Python and Dart implementations. * Update chart examples to use flet_charts as fch Refactored imports in candlestick, pie, and scatter chart examples to consistently use 'flet_charts as fch' instead of 'ftc'. Updated all references to chart classes and constants accordingly. Also fixed a color constant typo in pie chart example. * Update scrollable_control.py
1 parent d7a9b9d commit 6b84074

File tree

20 files changed

+248
-82
lines changed

20 files changed

+248
-82
lines changed

packages/flet/lib/src/utils/theme.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ ThemeData parseTheme(
136136
canvasColor: parseColor(value?["canvas_color"], theme),
137137
scaffoldBackgroundColor: parseColor(value?["scaffold_bgcolor"], theme),
138138
cardColor: parseColor(value?["card_bgcolor"], theme),
139-
dividerColor: dividerTheme?.color,
139+
dividerColor: parseColor(value?["divider_color"], theme),
140140
hintColor: parseColor(value?["hint_color"], theme),
141141
shadowColor: colorScheme?.shadow,
142142
secondaryHeaderColor: parseColor(value?["secondary_header_color"], theme),

sdk/python/examples/apps/routing-navigation/building-views-on-route-change.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,14 @@ def main(page: ft.Page):
66

77
print("Initial route:", page.route)
88

9-
def route_change(e):
10-
print("Route change:", e.route)
9+
async def open_mail_settings(e):
10+
await page.push_route("/settings/mail")
11+
12+
async def open_settings(e):
13+
await page.push_route("/settings")
14+
15+
def route_change():
16+
print("Route change:", page.route)
1117
page.views.clear()
1218
page.views.append(
1319
ft.View(
@@ -50,22 +56,17 @@ def route_change(e):
5056
)
5157
page.update()
5258

53-
def view_pop(e):
54-
print("View pop:", e.view)
55-
page.views.pop()
56-
top_view = page.views[-1]
57-
page.go(top_view.route)
59+
async def view_pop(e):
60+
if e.view is not None:
61+
print("View pop:", e.view)
62+
page.views.remove(e.view)
63+
top_view = page.views[-1]
64+
await page.push_route(top_view.route)
5865

5966
page.on_route_change = route_change
6067
page.on_view_pop = view_pop
6168

62-
def open_mail_settings(e):
63-
page.go("/settings/mail")
64-
65-
def open_settings(e):
66-
page.go("/settings")
67-
68-
page.go(page.route)
69+
route_change()
6970

7071

7172
ft.app(target=main, view=ft.AppView.WEB_BROWSER)
Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,55 @@
1+
import asyncio
2+
13
import flet as ft
24

35

46
def main(page: ft.Page):
57
page.title = "Routes Example"
68

7-
def route_change(e):
9+
def route_change():
810
page.views.clear()
911
page.views.append(
1012
ft.View(
11-
"/",
12-
[
13+
route="/",
14+
controls=[
1315
ft.AppBar(
1416
title=ft.Text("Flet app"), bgcolor=ft.Colors.SURFACE_BRIGHT
1517
),
16-
ft.Button("Visit Store", on_click=lambda _: page.go("/store")),
18+
ft.Button(
19+
"Visit Store",
20+
on_click=lambda: asyncio.create_task(page.push_route("/store")),
21+
),
1722
],
1823
)
1924
)
2025
if page.route == "/store":
2126
page.views.append(
2227
ft.View(
23-
"/store",
24-
[
28+
route="/store",
29+
controls=[
2530
ft.AppBar(
2631
title=ft.Text("Store"), bgcolor=ft.Colors.SURFACE_BRIGHT
2732
),
28-
ft.Button("Go Home", on_click=lambda _: page.go("/")),
33+
ft.Button(
34+
"Go Home",
35+
on_click=lambda: asyncio.create_task(page.push_route("/")),
36+
),
2937
],
3038
)
3139
)
3240
page.update()
3341

34-
def view_pop(e):
35-
page.views.pop()
36-
top_view = page.views[-1]
37-
page.go(top_view.route)
42+
async def view_pop(e):
43+
if e.view is not None:
44+
print("View pop:", e.view)
45+
page.views.remove(e.view)
46+
top_view = page.views[-1]
47+
await page.push_route(top_view.route)
3848

3949
page.on_route_change = route_change
4050
page.on_view_pop = view_pop
4151

42-
page.go(page.route)
52+
route_change()
4353

4454

4555
ft.run(main)

sdk/python/examples/apps/routing-navigation/initial-route.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ def main(page: Page):
66
page.add(Text(f"Initial route: {page.route}"))
77

88

9-
flet.app(target=main, view=flet.AppView.WEB_BROWSER)
9+
flet.run(main)

sdk/python/examples/apps/routing-navigation/requirements.txt

Lines changed: 0 additions & 1 deletion
This file was deleted.

sdk/python/examples/apps/routing-navigation/route-change-event.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ def route_change(e):
1212
page.update()
1313

1414

15-
flet.app(target=main, view=flet.AppView.WEB_BROWSER)
15+
flet.run(main)

sdk/python/examples/controls/charts/candlestick_chart/example_1.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import flet as ft
2-
import flet_charts as ftc
2+
import flet_charts as fch
33

44
CANDLE_DATA = [
55
("Mon", 24.8, 28.6, 23.9, 27.2),
@@ -12,19 +12,19 @@
1212
]
1313

1414

15-
def build_spots() -> list[ftc.CandlestickChartSpot]:
15+
def build_spots() -> list[fch.CandlestickChartSpot]:
1616
"""Create candlestick spots from the static data."""
17-
spots: list[ftc.CandlestickChartSpot] = []
17+
spots: list[fch.CandlestickChartSpot] = []
1818
for index, (label, open_, high, low, close) in enumerate(CANDLE_DATA):
1919
spots.append(
20-
ftc.CandlestickChartSpot(
20+
fch.CandlestickChartSpot(
2121
x=float(index),
2222
open=open_,
2323
high=high,
2424
low=low,
2525
close=close,
2626
selected=index == len(CANDLE_DATA) - 1,
27-
tooltip=ftc.CandlestickChartSpotTooltip(
27+
tooltip=fch.CandlestickChartSpotTooltip(
2828
text=(
2929
f"{label}\n"
3030
f"Open: {open_:0.1f}\n"
@@ -52,7 +52,7 @@ def main(page: ft.Page):
5252
min_y = min(low for _, _, _, low, _ in CANDLE_DATA) - 1
5353
max_y = max(high for _, _, _, _, high in CANDLE_DATA) + 1
5454

55-
def handle_event(e: ftc.CandlestickChartEvent):
55+
def handle_event(e: fch.CandlestickChartEvent):
5656
if e.spot_index is not None and e.spot_index >= 0:
5757
label, open_, high, low, close = CANDLE_DATA[e.spot_index]
5858
info.value = (
@@ -63,7 +63,7 @@ def handle_event(e: ftc.CandlestickChartEvent):
6363
info.value = f"{e.type.value} • outside candlesticks"
6464
info.update()
6565

66-
chart = ftc.CandlestickChart(
66+
chart = fch.CandlestickChart(
6767
expand=True,
6868
min_x=min_x,
6969
max_x=max_x,
@@ -72,17 +72,17 @@ def handle_event(e: ftc.CandlestickChartEvent):
7272
baseline_x=0,
7373
baseline_y=min_y,
7474
bgcolor=ft.Colors.with_opacity(0.2, ft.Colors.BLUE_GREY_900),
75-
horizontal_grid_lines=ftc.ChartGridLines(interval=2, dash_pattern=[2, 2]),
76-
vertical_grid_lines=ftc.ChartGridLines(interval=1, dash_pattern=[2, 2]),
77-
left_axis=ftc.ChartAxis(
75+
horizontal_grid_lines=fch.ChartGridLines(interval=2, dash_pattern=[2, 2]),
76+
vertical_grid_lines=fch.ChartGridLines(interval=1, dash_pattern=[2, 2]),
77+
left_axis=fch.ChartAxis(
7878
label_spacing=2,
7979
label_size=60,
8080
title=ft.Text("Price (k USD)", color=ft.Colors.GREY_300),
8181
show_min=False,
8282
),
83-
bottom_axis=ftc.ChartAxis(
83+
bottom_axis=fch.ChartAxis(
8484
labels=[
85-
ftc.ChartAxisLabel(
85+
fch.ChartAxisLabel(
8686
value=index,
8787
label=ft.Text(name, color=ft.Colors.GREY_300),
8888
)
@@ -94,9 +94,9 @@ def handle_event(e: ftc.CandlestickChartEvent):
9494
show_max=False,
9595
),
9696
spots=spots,
97-
tooltip=ftc.CandlestickChartTooltip(
97+
tooltip=fch.CandlestickChartTooltip(
9898
bgcolor=ft.Colors.BLUE_GREY_800,
99-
horizontal_alignment=ftc.HorizontalAlignment.CENTER,
99+
horizontal_alignment=fch.HorizontalAlignment.CENTER,
100100
fit_inside_horizontally=True,
101101
),
102102
on_event=handle_event,
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import asyncio
2+
import random
3+
from dataclasses import dataclass, field
4+
5+
import flet as ft
6+
import flet_charts as ft_charts
7+
8+
MAX_POINTS = 20
9+
10+
11+
@dataclass
12+
class DataPoint:
13+
x: float
14+
y: float
15+
16+
17+
@dataclass
18+
@ft.observable
19+
class ChartData:
20+
x: float = 0.0
21+
min_y: float = 0.0
22+
max_y: float = 1.0
23+
points: list[DataPoint] = field(default_factory=list)
24+
25+
def __post_init__(self):
26+
for _ in range(MAX_POINTS):
27+
self.add_point()
28+
29+
def add_point(self):
30+
self.points.append(
31+
DataPoint(x=self.x, y=random.uniform(self.min_y, self.max_y))
32+
)
33+
self.x += 0.5
34+
if len(self.points) > MAX_POINTS:
35+
self.points.pop(0)
36+
37+
38+
@ft.component
39+
def Gauge(
40+
min_y: float = 0.0,
41+
max_y: float = 1.0,
42+
width: int = 200,
43+
height: int = 150,
44+
line_color=ft.Colors.BLUE,
45+
bgcolor=ft.Colors.BLUE_100,
46+
):
47+
chart_data, _ = ft.use_state(lambda: ChartData(min_y=min_y, max_y=max_y))
48+
49+
async def generate_chart_data():
50+
for _ in range(0, 100):
51+
chart_data.add_point()
52+
await asyncio.sleep(1.0)
53+
54+
ft.on_mounted(generate_chart_data)
55+
56+
return ft_charts.LineChart(
57+
data_series=[
58+
ft_charts.LineChartData(
59+
stroke_width=2,
60+
color=line_color,
61+
curved=True,
62+
points=[
63+
ft_charts.LineChartDataPoint(
64+
key=point.x,
65+
x=point.x,
66+
y=point.y,
67+
selected_point=ft_charts.ChartCirclePoint(radius=4),
68+
selected_below_line=False,
69+
tooltip=f"{round(point.y, 2)}%",
70+
)
71+
for point in chart_data.points
72+
],
73+
below_line_bgcolor=bgcolor,
74+
)
75+
],
76+
border=ft.Border.all(1, ft.Colors.GREY_400),
77+
horizontal_grid_lines=ft_charts.ChartGridLines(
78+
color=ft.Colors.GREY_300, width=1, dash_pattern=[3, 3], interval=0.1
79+
),
80+
tooltip=ft_charts.LineChartTooltip(
81+
bgcolor=ft.Colors.BLACK_12,
82+
border_radius=4,
83+
padding=ft.Padding(5),
84+
),
85+
min_y=0,
86+
max_y=1,
87+
width=width,
88+
height=height,
89+
animation=ft.Animation(duration=0),
90+
)
91+
92+
93+
@ft.component
94+
def App():
95+
return ft.Row(
96+
controls=[
97+
ft.Column(
98+
[
99+
ft.Text("CPU Usage"),
100+
Gauge(
101+
min_y=0.3,
102+
max_y=1.0,
103+
line_color=ft.Colors.BLUE,
104+
bgcolor=ft.Colors.BLUE_100,
105+
),
106+
],
107+
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
108+
),
109+
ft.Column(
110+
[
111+
ft.Text("Memory Usage"),
112+
Gauge(
113+
min_y=0.2,
114+
max_y=0.5,
115+
line_color=ft.Colors.GREEN,
116+
bgcolor=ft.Colors.GREEN_100,
117+
),
118+
],
119+
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
120+
),
121+
ft.Column(
122+
[
123+
ft.Text("Disk Usage"),
124+
Gauge(
125+
min_y=0.7,
126+
max_y=0.9,
127+
line_color=ft.Colors.ORANGE,
128+
bgcolor=ft.Colors.ORANGE_100,
129+
),
130+
],
131+
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
132+
),
133+
]
134+
)
135+
136+
137+
ft.run(lambda page: page.render(App))

sdk/python/examples/controls/charts/pie_chart/example_3.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import flet_charts as fch
2-
31
import flet as ft
2+
import flet_charts as fch
43

54
NORMAL_RADIUS = 100
65
HOVER_RADIUS = 110
@@ -11,7 +10,7 @@
1110
size=16,
1211
color=ft.Colors.WHITE,
1312
weight=ft.FontWeight.BOLD,
14-
shadow=ft.BoxShadow(blur_radius=2, color=ft.Colors.BLACK54),
13+
shadow=ft.BoxShadow(blur_radius=2, color=ft.Colors.BLACK_54),
1514
)
1615
NORMAL_BADGE_SIZE = 40
1716
HOVER_BADGE_SIZE = 50

0 commit comments

Comments
 (0)