From 13963abe51def347a3829174efe64b8dd68b1fbb Mon Sep 17 00:00:00 2001 From: Hong-Phuc Bui <hong-phuc.bui@htwsaar.de> Date: Fri, 30 May 2025 11:06:44 +0200 Subject: [PATCH] NiceGUI vs Tk 27.5.2025 --- nicegui-tk-bezier/.gitignore | 3 .gitignore | 12 ++ python-typing/python-typing.handout.pdf | 0 python-typing/python-typing.presentation.pdf | 0 nicegui-tk-bezier/README.md | 24 ++++ nicegui-tk-bezier/bezier.py | 43 ++++++++ nicegui-tk-bezier/main-nicegui.py | 28 +++++ /dev/null | 10 -- nicegui-tk-bezier/requirements.txt | 1 nicegui-tk-bezier/main-canvas.py | 36 +++++++ nicegui-tk-bezier/dummy.txt | 52 ++++++++++ python-typing/py-type-demo/measure.py | 17 ++ python-typing/python-typing.tex | 34 +++++- 13 files changed, 240 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..813620a --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +*.aux +*.log +*.snm +*.out +*.synctex.gz +*.toc +*.vrb +*.nav +_minted-*/ +*.idea/ + + diff --git a/nicegui-tk-bezier/.gitignore b/nicegui-tk-bezier/.gitignore new file mode 100644 index 0000000..31dc02d --- /dev/null +++ b/nicegui-tk-bezier/.gitignore @@ -0,0 +1,3 @@ +.venv/ +.idea/ +__pycache__/ \ No newline at end of file diff --git a/nicegui-tk-bezier/README.md b/nicegui-tk-bezier/README.md new file mode 100644 index 0000000..8df778b --- /dev/null +++ b/nicegui-tk-bezier/README.md @@ -0,0 +1,24 @@ +# Demo NiceGUI vs Tk + +## Install + +```bash +python3.13 -m venv .venv +source .venv/bin/activate +pip install -r requirements.txt +``` + + +## Run + +### Tk + +```bash +python ./main-canvas.py +``` + +### NiceGUI + +```bash +python ./main-nicegui.py +``` diff --git a/nicegui-tk-bezier/bezier.py b/nicegui-tk-bezier/bezier.py new file mode 100644 index 0000000..b491a1a --- /dev/null +++ b/nicegui-tk-bezier/bezier.py @@ -0,0 +1,43 @@ +"""" +Module related to bezier curve +""" +def make_cubic_bezier(control_points: [(float, float)], n: int = 10) -> [(float, float)]: + """" + Interpolate a Bezier-curve by split it into segments of lines (=polyline). + A Bezier-Curve is defined by + + \[ + B(P_0, P_1, P_2, P_3:t) = (1-t)^3*P_0 + 3(1-t)^2*t*P_1 + 3(1-t)*t^2*P_2 + t^3*P_3 + \] + + for $t \in \[0, 1\]$ + + :param control_points + :param n number of segments + :return a list of points on the Bezier-Curve. + """ + + p0x = control_points[0][0] + p0y = control_points[0][1] + p1x = control_points[1][0] + p1y = control_points[1][1] + p2x = control_points[2][0] + p2y = control_points[2][1] + p3x = control_points[3][0] + p3y = control_points[3][1] + points = [(p0x, p0y)] + for i in range(1, n): + t = i / n + u = 1 - t + x = p0x * u**3 + 3 * p1x * t* u**2 + 3 * p2x * t**2 * u + p3x * t**3 + y = p0y * u**3 + 3 * p1y * t* u**2 + 3 * p2y * t**2 * u + p3y * t**3 + points.append( (x,y) ) + points.append((p3x, p3y)) + return points + + +def make_svg_polyline(points) -> str: + line = map(lambda p: f"{p[0]},{p[1]}", points) + svg = f'<polyline points="{" ".join(line)}" fill="none" stroke="gray" stroke-width="3" />' + return svg + diff --git a/nicegui-tk-bezier/dummy.txt b/nicegui-tk-bezier/dummy.txt new file mode 100644 index 0000000..08d13e5 --- /dev/null +++ b/nicegui-tk-bezier/dummy.txt @@ -0,0 +1,52 @@ +aiofiles==24.1.0 +aiohappyeyeballs==2.6.1 +aiohttp==3.12.4 +aiosignal==1.3.2 +annotated-types==0.7.0 +anyio==4.9.0 +attrs==25.3.0 +bidict==0.23.1 +certifi==2025.4.26 +charset-normalizer==3.4.2 +click==8.2.1 +docutils==0.21.2 +fastapi==0.115.12 +frozenlist==1.6.0 +h11==0.16.0 +httpcore==1.0.9 +httptools==0.6.4 +httpx==0.28.1 +idna==3.10 +ifaddr==0.2.0 +itsdangerous==2.2.0 +Jinja2==3.1.6 +markdown2==2.5.3 +MarkupSafe==3.0.2 +multidict==6.4.4 +nicegui==2.18.0 +orjson==3.10.18 +propcache==0.3.1 +pscript==0.7.7 +pydantic==2.11.5 +pydantic_core==2.33.2 +Pygments==2.19.1 +python-dotenv==1.1.0 +python-engineio==4.12.1 +python-multipart==0.0.20 +python-socketio==5.13.0 +PyYAML==6.0.2 +requests==2.32.3 +simple-websocket==1.1.0 +sniffio==1.3.1 +starlette==0.46.2 +typing-inspection==0.4.1 +typing_extensions==4.13.2 +urllib3==2.4.0 +uvicorn==0.34.2 +uvloop==0.21.0 +vbuild==0.8.2 +wait_for2==0.3.2 +watchfiles==1.0.5 +websockets==15.0.1 +wsproto==1.2.0 +yarl==1.20.0 diff --git a/nicegui-tk-bezier/main-canvas.py b/nicegui-tk-bezier/main-canvas.py new file mode 100644 index 0000000..756cfa8 --- /dev/null +++ b/nicegui-tk-bezier/main-canvas.py @@ -0,0 +1,36 @@ +from tkinter import * + +from bezier import make_cubic_bezier + +def draw_bezier(canvas, control_points): + points = make_cubic_bezier(control_points, n= 400) + for i in range(1,len(points)): + x1 = points[i-1][0] + y1 = points[i-1][1] + x2 = points[i][0] + y2 = points[i][1] + canvas.create_line(x1,y1, x2,y2) + + +def get_point(event): + global control_points + point = x, y = (event.x, event.y) + control_points.append(point) + canvas.create_oval(x, y, x+3, y+3) + if len(control_points) == 4: + draw_bezier(canvas, control_points) + control_points = [] + + +if __name__ == '__main__': + + control_points = [] + + root = Tk() + + canvas = Canvas(root, width=800, height=800) + canvas.pack() + + canvas.bind('<Button-1>', get_point) + + root.mainloop() \ No newline at end of file diff --git a/nicegui-tk-bezier/main-nicegui.py b/nicegui-tk-bezier/main-nicegui.py new file mode 100644 index 0000000..4a055ea --- /dev/null +++ b/nicegui-tk-bezier/main-nicegui.py @@ -0,0 +1,28 @@ +from nicegui import ui + +from bezier import make_cubic_bezier, make_svg_polyline + +control_points = [] +svg = "" + +def get_point(event): + global control_points + global svg + x = event.image_x + y = event.image_y + control_points.append((x,y)) + svg += f'<circle cx="{x}" cy="{y}" r="1" fill="orange" />' + ui.notification(f"(x,y) = ({x},{y})") + if len(control_points) == 4: + bezier_points = make_cubic_bezier(control_points, n = 50) + svg += make_svg_polyline(bezier_points) + control_points.clear() + event.sender.set_content(svg) + +ui.interactive_image( + size=(900, 400), cross=True, + on_mouse=get_point, +).classes('w-full bg-blue-50') + +ui.run() + diff --git a/nicegui-tk-bezier/requirements.txt b/nicegui-tk-bezier/requirements.txt new file mode 100644 index 0000000..e57426a --- /dev/null +++ b/nicegui-tk-bezier/requirements.txt @@ -0,0 +1 @@ +nicegui==2.18.0 diff --git a/python-typing/py-type-demo/.idea/.gitignore b/python-typing/py-type-demo/.idea/.gitignore deleted file mode 100644 index 26d3352..0000000 --- a/python-typing/py-type-demo/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/python-typing/py-type-demo/.idea/inspectionProfiles/profiles_settings.xml b/python-typing/py-type-demo/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2d..0000000 --- a/python-typing/py-type-demo/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ -<component name="InspectionProjectProfileManager"> - <settings> - <option name="USE_PROJECT_PROFILE" value="false" /> - <version value="1.0" /> - </settings> -</component> \ No newline at end of file diff --git a/python-typing/py-type-demo/.idea/misc.xml b/python-typing/py-type-demo/.idea/misc.xml deleted file mode 100644 index 5f683b8..0000000 --- a/python-typing/py-type-demo/.idea/misc.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project version="4"> - <component name="Black"> - <option name="sdkName" value="Python 3.12 (py-type-demo)" /> - </component> - <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (py-type-demo)" project-jdk-type="Python SDK" /> -</project> \ No newline at end of file diff --git a/python-typing/py-type-demo/.idea/modules.xml b/python-typing/py-type-demo/.idea/modules.xml deleted file mode 100644 index 0a4f4ae..0000000 --- a/python-typing/py-type-demo/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project version="4"> - <component name="ProjectModuleManager"> - <modules> - <module fileurl="file://$PROJECT_DIR$/.idea/py-type-demo.iml" filepath="$PROJECT_DIR$/.idea/py-type-demo.iml" /> - </modules> - </component> -</project> \ No newline at end of file diff --git a/python-typing/py-type-demo/.idea/py-type-demo.iml b/python-typing/py-type-demo/.idea/py-type-demo.iml deleted file mode 100644 index 2c80e12..0000000 --- a/python-typing/py-type-demo/.idea/py-type-demo.iml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="PYTHON_MODULE" version="4"> - <component name="NewModuleRootManager"> - <content url="file://$MODULE_DIR$"> - <excludeFolder url="file://$MODULE_DIR$/.venv" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - </component> -</module> \ No newline at end of file diff --git a/python-typing/py-type-demo/measure.py b/python-typing/py-type-demo/measure.py index 2da05d4..fb2180c 100644 --- a/python-typing/py-type-demo/measure.py +++ b/python-typing/py-type-demo/measure.py @@ -1,12 +1,20 @@ -from typing import Sequence, Callable, TypeAlias - -measurement: Sequence[int | float] = [12.5, 11, 12.3, 11.6, 11.1, 12] - +from typing import Sequence, Callable, TypeAlias, Iterable def avg(values: Sequence[int | float]) -> float: return sum(values) / len(values) +length: list[int | float] = [12.5, 11, 12.3, 11.6, 11.1, 12] +length_avg = avg(length) + +count_member: tuple[int, int, int, int, int] = (12, 15, 16, 11, 10) +member_avg = avg(count_member) +print(member_avg) + +prime_set: set[int] = {2, 3, 5, 7, 11} # +prime_avg = avg(prime_set) + +""" avg: Callable[[Sequence[int | float]], float] = \ lambda values: sum(values) / len(values) @@ -15,3 +23,4 @@ avg: Callable[[Scale], float] = \ lambda v: sum(v) / len(v) if len(v) > 0 else 0.0 +""" \ No newline at end of file diff --git a/python-typing/python-typing.handout.pdf b/python-typing/python-typing.handout.pdf index 49ae66c..67a99a3 100644 --- a/python-typing/python-typing.handout.pdf +++ b/python-typing/python-typing.handout.pdf Binary files differ diff --git a/python-typing/python-typing.presentation.pdf b/python-typing/python-typing.presentation.pdf index 60f835b..bae2c02 100644 --- a/python-typing/python-typing.presentation.pdf +++ b/python-typing/python-typing.presentation.pdf Binary files differ diff --git a/python-typing/python-typing.tex b/python-typing/python-typing.tex index 52fc9e2..8043724 100644 --- a/python-typing/python-typing.tex +++ b/python-typing/python-typing.tex @@ -124,14 +124,11 @@ \end{minted} \end{frame} -\subsection{Union} +\subsection{Union und Generic} \begin{frame}[fragile] \frametitle{Union} \begin{minted}{python} -from typing import Sequence - - -measurement: Sequence[int | float] = [12.5, 11, 12.3, 11.6, 11.1, 12] +measurement: list[int | float] = [12.5, 11, 12.3, 11.6, 11.1, 12] \end{minted} \pause @@ -140,7 +137,7 @@ \begin{frame}[fragile] -\frametitle{Funktionsparameter} +\frametitle{Generic} \begin{minted}{python} def avg(values: Sequence[int | float]) -> float: @@ -156,6 +153,31 @@ \end{minted} \end{frame} +\begin{frame}[fragile] +\frametitle{Aufruf} +\begin{minted}{python} +# List Ok +length: list[int | float] = [12.5, 11, 12.3, 11.6, 11.1, 12] +length_avg = avg(length) + +# Tupel Ok +count_member: tuple[int, int, int, int, int] = (12, 15, 16, 11, 10) +member_avg = avg(count_member) +\end{minted} +\end{frame} + +\begin{frame}[fragile] +\frametitle{Pitfall} +\begin{minted}{python} +# Set is not a Sequence +my_set: set[int] = {2, 3, 5, 7, 11} # +prime_avg = avg(prime_set) + + +# mypy: +# ...incompatible type "Set[int]"; expected "Sequence[Union[int, float]]" +\end{minted} +\end{frame} \subsection{TypeAlias} \begin{frame}[fragile] -- Gitblit v1.10.0-SNAPSHOT