Dieser Artikel ist der Artikel zum 16. Tag von Lisp Adventskalender 2019.
Als Einführung in die GUI-Programmierung in Hy wird generative Kunst unter Verwendung der GUI-Bibliothek tkinter in die Standard-Python-Bibliothek aufgenommen. Implementieren.
Es ist eine Spezifikation, dass Sie die Parameter durch Tasteneingabe beim Zeichnen einer Figur mit einer Dreiecksfunktion wie dieser ändern können.
Die Umgebung des Autors ist wie folgt.
Die GUI-Bibliothek tkinter ist eine Standard-Python-Bibliothek, daher ist Hy das einzige Modul eines Drittanbieters, das in einer virtuellen Umgebung installiert wird. Hy hat die neueste Version ab 12/10 installiert (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
Erstellen Sie eine Leinwand in dem Fenster, das als tk.Tk () -Instanz erstellt wurde, und zeichnen Sie eine Figur darin. Zeichnen Sie die Leinwand für Animationen mit ca. 60 fps neu. Die Koordinaten eines Punktes zu einem bestimmten Zeitpunkt werden nach der folgenden Formel berechnet. Ändern Sie $ \ theta $ um $ \ mathrm {d} \ theta $, um zu diesem Zeitpunkt ein Array von Punkten zu erstellen.
\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) $ ist die Mittelkoordinate des Canvas. $ \ phi $ bewirkt, dass $ 0 \ leq \ phi <2 \ pi $ im Laufe der Zeit eine Schleife durchläuft.
Ermöglicht es Ihnen, die Schrittgröße $ \ mathrm {d} \ theta $ von $ r, a, c $ und $ \ theta $ oben durch Eingabe zu ändern. Die Tastenbelegungen sind in der folgenden Tabelle aufgeführt. Außerdem wird die Taste q zum Schließen und Verlassen des Fensters festgelegt.
Variable | Schlüssel verringern | Schlüssel erhöhen |
---|---|---|
z | a | |
x | s | |
c | d | |
v | f |
hy
Angenommen, das Verzeichnis wurde zu Pythonpath hinzugefügt.
Der Inhalt von \ _ \ _ init \ _ \ _. Hy ist leer, und wir werden die Funktion in gui.hy implementieren.
Rufen Sie geometric_pattern.gui aus geometric_pattern.bat auf und führen Sie es aus.
hy ─┬─ geometric_pattern ─┬─ __init__.hy
│ │
│ └─ gui.hy
│
└─ geometric_pattern.bat
gui.hy
(import [math [sin cos radians]])
(import sys)
(import [tkinter :as tk])
;Leinwandgröße
(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]]
"Initialisieren Sie die Parameter und erhalten Sie eine Liste mit Punkten"
(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)
;;Schrittweite beim Thetawechsel
(setv (. self d-theta) 1)
((. self fetch-points)))
(defn dec-r [self event]
"Verringern Sie r"
(setv (. self r) (dec (. self r)))
(if (< (. self r) 1)
(setv (. self r) 1)))
(defn inc-r [self event]
"Erhöhen Sie r. Die Obergrenze ist so festgelegt, dass sie nicht aus der kurzen Seite von Canvas herausragt"
(if (< (+ (. self r) (. self a))
(min (. self center-x) (. self center-y)))
(setv (. self r) (inc (. self r)))))
(defn dec-a [self event]
"Verringern Sie a"
(setv (. self a) (dec (. self a)))
(if (< (. self a) 1)
(setv (. self a) 1)))
(defn inc-a [self event]
"Erhöhen Sie a. Die Obergrenze ist so festgelegt, dass sie nicht aus der kurzen Seite von Canvas herausragt"
(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]
"Holen Sie sich die Koordinaten eines Punktes"
(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)))))))))
;;Fügen Sie den ersten Punkt am Ende der Liste hinzu, um den Pfad zu schließen
((. self points append) (. self points [0]))))
(defclass Simulator []
(setv *ms* 16)
(defn --init-- [self width height]
(setv (. self width) width)
(setv (. self height) height)
;;Fenster- und Canvas-Initialisierung
(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))
;;Koordinaten der anzuzeigenden Zeichen
(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)))
;;Fülle die Leinwand mit der Hintergrundfarbe (schwarz)
((. self canvas create-rectangle) 0
0
(. self width)
(. self height)
:fill "black")
((. self draw))
((. self canvas pack))
;;Einstellungen für die Schlüsselbindung
((. 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]
;;Eine Figur zeichnen
((. self canvas create-line) (. self gp points) :fill "white" :tag "sample")
;;Zeichen zeichnen
((. 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]
"Löschen Sie das Element mit dem Beispiel-Tag"
((. self canvas delete) "sample"))
(defn loop [self]
;;Löschen Sie den vorherigen Bildschirm
((. self delete))
;;Holen Sie sich neuen Zustand und zeichnen
((. self gp inc-phi))
((. self gp fetch-points))
((. self draw))
;;Schleife nach ca. 16ms ausführen
((. 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)))
Erstellen Sie eine Batch-Datei, um das obige geometric_pattern.gui-Modul aufzurufen und auszuführen.
`Aktiviere``` die virtuelle Umgebung, so dass sich der Befehl`
hy und das hy-Modul im Pfad befinden. Führen Sie dann das Modul geometric_pattern.gui mit dem Befehl `` `hy
aus.
Mit der Option -m können Sie die Module im Paket in punktgetrennter Notation angeben.
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
)
Machen wir das.
Ja. Es kann Spaß machen, die Farbe und Dicke des Pfades oder eine andere Formel zu ändern.
Recommended Posts