Cet article est l'article du 16ème jour du Calendrier de l'Avent Lisp 2019.
En guise d'introduction à la programmation GUI dans Hy, l'art génératif utilisant la bibliothèque GUI tkinter inclus dans la bibliothèque Python standard. Implémenter.
C'est une spécification que vous pouvez modifier les paramètres par entrée clé dans le dessin d'une figure en utilisant une fonction triangulaire comme celle-ci.
L'environnement de l'auteur est le suivant.
La bibliothèque GUI tkinter est une bibliothèque Python standard, Hy est donc le seul module tiers à installer dans un environnement virtuel. Hy a installé la dernière version en date du 12/10 (https://github.com/hylang/hy/tree/39c150d8299d9ff8f47bb78415e22a9fe976d7e5).
cd %USERPROFILE$\.virtualenvs
py -3 -m venv venv_hy_geometric_pattern
cd venv_hy_geometric_pattern
Scripts\activate.bat
pip install --upgrade pip
pip install git+https://github.com/hylang/hy.git
deactivate
tk.Tk () Créez un canevas dans la fenêtre créée en tant qu'occurrence et dessinez-y une figure. Redessinez le canevas à environ 60 ips pour l'animation. Les coordonnées d'un point à un certain moment sont calculées par la formule suivante. Changez $ \ theta $ par $ \ mathrm {d} \ theta $ pour créer un tableau de points à ce moment-là.
\left\{ \begin{array}{}
x(\theta , t) = x_{\mathrm{center}} + r \cos \theta + a \cos (\phi \left( t \right) + c \theta) \\
y(\theta , t) = y_{\mathrm{center}} + r \sin \theta + a \sin (\phi \left( t \right) + c \theta)
\end{array} \right.
0 \leq \theta < 2 \pi \\
0 \leq \phi < 2 \pi \\
0 \leq c < 2 \pi \\
0 < r + a < \min(x_{\mathrm{center}}, y_{\mathrm{center}}) \\
$ \ left (x_ {\ mathrm {center}}, y_ {\ mathrm {center}} \ right) $ est la coordonnée centrale du canevas. $ \ phi $ fait boucler $ 0 \ leq \ phi <2 \ pi $ dans le temps.
Vous permet de changer la taille de pas $ \ mathrm {d} \ theta $ de $ r, a, c $ et $ \ theta $ ci-dessus par saisie. Les affectations des touches sont indiquées dans le tableau ci-dessous. Il définit également la touche q pour fermer et quitter la fenêtre.
variable | Diminuer la clé | Augmenter la clé |
---|---|---|
z | a | |
x | s | |
c | d | |
v | f |
hy
Supposons que le répertoire a été ajouté à pythonpath.
Le contenu de \ _ \ _ init \ _ \ _. Hy est vide, et nous implémenterons la fonction dans gui.hy.
Appelez et exécutez Geometric_pattern.gui à partir de Geometric_pattern.bat.
hy ─┬─ geometric_pattern ─┬─ __init__.hy
│ │
│ └─ gui.hy
│
└─ geometric_pattern.bat
gui.hy
(import [math [sin cos radians]])
(import sys)
(import [tkinter :as tk])
;Taille de la toile
(setv *width* 800)
(setv *height* 600)
(defclass GeometricPattern []
(setv *d-theta-max* 20)
(setv *deg* 360)
(setv *d-phi* 1)
(defn --init-- [self &optional [center-x 0] [center-y 0]]
"Initialisez les paramètres et obtenez une liste de points"
(setv (. self center-x) center-x)
(setv (. self center-y) center-y)
(setv (. self r)
(int (-> 0.8
(* (min (. self center-x) (. self center-y)))
(/ 3))))
(setv (. self a)
(int (-> 0.8
(* 2 (min (. self center-x) (. self center-y)))
(/ 3))))
(setv (. self phi) 0)
(setv (. self c) 104)
;;Largeur de pas lors du changement de thêta
(setv (. self d-theta) 1)
((. self fetch-points)))
(defn dec-r [self event]
"Diminuer r"
(setv (. self r) (dec (. self r)))
(if (< (. self r) 1)
(setv (. self r) 1)))
(defn inc-r [self event]
"Augmentez r. La limite supérieure est spécifiée afin qu'elle ne dépasse pas du côté court de Canvas"
(if (< (+ (. self r) (. self a))
(min (. self center-x) (. self center-y)))
(setv (. self r) (inc (. self r)))))
(defn dec-a [self event]
"Diminuer un"
(setv (. self a) (dec (. self a)))
(if (< (. self a) 1)
(setv (. self a) 1)))
(defn inc-a [self event]
"Augmentez a. La limite supérieure est spécifiée afin qu'elle ne dépasse pas du côté court de Canvas"
(if (< (+ (. self r) (. self a))
(min (. self center-x) (. self center-y)))
(setv (. self a) (inc (. self a)))))
(defn dec-d-theta [self event]
(setv (. self d-theta) (dec (. self d-theta)))
(if (< (. self d-theta) 1)
(setv (. self d-theta) 1)))
(defn inc-d-theta [self event]
(setv (. self d-theta) (inc (. self d-theta)))
(if (> (. self d-theta) (. GeometricPattern *d-theta-max*))
(setv (. self d-theta) (. GeometricPattern *d-theta-max*))))
(defn dec-c [self event]
(setv (. self c) (dec (. self c)))
(if (< (. self c) 0)
(setv (. self c) (% (. self c) (. GeometricPattern *deg*)))))
(defn inc-c [self event]
(setv (. self c) (inc (. self c)))
(if (>= (. self c) (. GeometricPattern *deg*))
(setv (. self c) (% (. self c) (. GeometricPattern *deg*)))))
(defn inc-phi [self]
(setv (. self phi) (inc (. self phi)))
(setv (. self phi) (% (. self phi) (. GeometricPattern *deg*))))
(defn fetch-points [self]
"Obtenir les coordonnées d'un point"
(setv (. self points)
(lfor theta (range 0 (. GeometricPattern *deg*) (. self d-theta))
(, (+ (+ (. self center-x) (* (. self r) (cos (radians theta))))
(* (. self a) (cos (radians (+ (. self phi) (* (. self c) theta))))))
(+ (+ (. self center-y) (* (. self r) (sin (radians theta))))
(* (. self a) (sin (radians (+ (. self phi) (* (. self c) theta)))))))))
;;Ajoutez le premier point à la fin de la liste pour fermer le chemin
((. self points append) (. self points [0]))))
(defclass Simulator []
(setv *ms* 16)
(defn --init-- [self width height]
(setv (. self width) width)
(setv (. self height) height)
;;Initialisation de la fenêtre et du canevas
(setv (. self window) ((. tk Tk)))
((. self window title) :string "Sample Trig Function on Tkinter")
((. self window resizable) :width False :height False)
(setv (. self canvas)
((. tk Canvas) (. self window)
:width (. self width)
:height (. self height)))
(setv (. self center-x) (/ width 2))
(setv (. self center-y) (/ height 2))
;;Coordonnées des caractères à afficher
(setv (. self quit-x) 20)
(setv (. self quit-y) 30)
(setv (. self r-x) (- width 20))
(setv (. self r-y) (- height 120))
(setv (. self a-x) (- width 20))
(setv (. self a-y) (- height 90))
(setv (. self c-x) (- width 20))
(setv (. self c-y) (- height 60))
(setv (. self d-theta-x) (- width 20))
(setv (. self d-theta-y) (- height 30))
(setv (. self gp) (GeometricPattern (. self center-x) (. self center-y)))
;;Remplissez la toile avec la couleur d'arrière-plan (noir)
((. self canvas create-rectangle) 0
0
(. self width)
(. self height)
:fill "black")
((. self draw))
((. self canvas pack))
;;Paramètres de liaison des clés
((. self window bind) "<KeyPress-q>" (. self quit))
((. self window bind) "<KeyPress-z>" (. self gp dec-r))
((. self window bind) "<KeyPress-a>" (. self gp inc-r))
((. self window bind) "<KeyPress-x>" (. self gp dec-a))
((. self window bind) "<KeyPress-s>" (. self gp inc-a))
((. self window bind) "<KeyPress-c>" (. self gp dec-c))
((. self window bind) "<KeyPress-d>" (. self gp inc-c))
((. self window bind) "<KeyPress-v>" (. self gp dec-d-theta))
((. self window bind) "<KeyPress-f>" (. self gp inc-d-theta)))
(defn quit [self event]
((. self window destroy)))
(defn draw [self]
;;Dessiner une figure
((. self canvas create-line) (. self gp points) :fill "white" :tag "sample")
;;Dessiner des personnages
((. self canvas create-text) (. self quit-x)
(. self quit-y)
:text "Quit: q"
:tag "sample"
:font (, "Arial" 12)
:fill "white"
:anchor (. tk W))
((. self canvas create-text) (. self r-x)
(. self r-y)
:text ((. "r: Z < {0:03d} > A" format) (. self gp r))
:tag "sample"
:font (, "Arial" 12)
:fill "white"
:anchor (. tk E))
((. self canvas create-text) (. self a-x)
(. self a-y)
:text ((. "a: X < {0:03d} > S" format) (. self gp a))
:tag "sample"
:font (, "Arial" 12)
:fill "white"
:anchor (. tk E))
((. self canvas create-text) (. self c-x)
(. self c-y)
:text ((. "c: C < {0:03d} > D" format) (. self gp c))
:tag "sample"
:font (, "Arial" 12)
:fill "white"
:anchor (. tk E))
((. self canvas create-text) (. self d-theta-x)
(. self d-theta-y)
:text ((. "d-theta: V < {0:03d} > F" format) (. self gp d-theta))
:tag "sample"
:font (, "Arial" 12)
:fill "white"
:anchor (. tk E)))
(defn delete [self]
"Supprimer l'élément avec la balise exemple"
((. self canvas delete) "sample"))
(defn loop [self]
;;Effacer l'écran précédent
((. self delete))
;;Obtenez un nouvel état et dessinez
((. self gp inc-phi))
((. self gp fetch-points))
((. self draw))
;;Exécuter la boucle après environ 16 ms
((. self window after) (. Simulator *ms*) (. self loop))))
(defn main []
(setv simulator (Simulator *width* *height*))
((. simulator loop))
((. simulator window mainloop))
0)
(when (= --name-- "__main__")
((. sys exit) (main)))
Créez un fichier de commandes pour appeler et exécuter le module géométrique_pattern.gui ci-dessus.
Activer
l'environnement virtuel pour que la commande `hy``` et le module hy soient dans le chemin. Exécutez ensuite le module Geometric_pattern.gui avec la commande
hy ''.
Avec l'option -m, vous pouvez spécifier les modules du package en notation séparée par des points.
geometric_pattern.bat
@ECHO OFF
SETLOCAL
SET THISDIR=%~dp0
SET PYTHONPATH=%THISDIR%;%PYTHONPATH%
SET ACTIVATE=%USERPROFILE%\.virtualenvs\venv_hy_geometric_pattern\Scripts\activate.bat
CALL %ACTIVATE%
hy -m geometric_pattern.gui
SET STATUS=%ERRORLEVEL%
CALL deactivate
IF %STATUS%==0 (
ECHO Done.
PAUSE
EXIT /b 0
) ELSE (
ECHO Error.
PAUSE
EXIT /b 1
)
Faisons le.
Oui. Il peut être amusant de changer la couleur et l'épaisseur du tracé ou de le changer en une autre formule.
Recommended Posts