Interface graphique python turtle

Fermé
Poufpaf - Modifié le 27 oct. 2022 à 14:03
mamiemando Messages postés 33064 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 12 avril 2024 - 2 nov. 2022 à 14:00

Bonjour,

J'utilise turtle pour faire une de simulation. J'aimerais :

  1. lancer le programme sous forme de shell (sans interface graphique) afin de pouvoir entrer des valeurs utiles pour la simulation dans un input ;
  2. puis lancer l'interface graphique avec la simulation, quand je le demanderais ;
  3. lorsque la simulation est terminée, revenir automatiquement à une interface shell normale.

Imaginons quelque chose comme :

import turtle
import math
import time

###lancer le programme sans interface graphique###

#forme_option = int(input("[1] #square\n[2] circle"))
#if forme_option == 1:
#    FORME = "square"
#else:
#    FORME = "circle"

###passer à l'interface graphique###


screen = turtle.Screen()
screen.bgcolor("#FFE800")
forme = turtle.Turtle()
forme.shape(FORME)
forme.shapesize(10, 10)
forme.color("#800080")
for t in range(100):
    n = 10*math.sin(t/30) + 1
    forme.shapesize(n, n)
    time.sleep(0.01)
turtle.done()


###fermer l'interface graphique et revenir à l'interface normalle###

#name = str(input("your name : "))
#print("end of simulation")
#print("\n  Goodbye !", name)

###fermer le programme###

Voilà, j'espère avoir été assez clair avec ce que je veux faire (lisez les # dans le code).

Merci de vos futures réponses

4 réponses

Bonsoir, ne peux-tu pas utiliser un input dans turtle ?
 

screen = turtle.Screen()
shape = turtle.textinput('Shape', "Type de forme (square ou circle)")

screen.bgcolor("#FFE800")
forme = turtle.Turtle()
forme.shape(shape)
# ...

En ajoutant un contrôle de la valeur de shape dans une boucle.

0
mamiemando Messages postés 33064 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 12 avril 2024 7 744
Modifié le 27 oct. 2022 à 15:15

Bonjour,

Vu quand le cas présent, il s'agit de tracer une fonction mathématique, as-tu considérer de plutôt utiliser pyplot (et la fonction replot) pour faire ton animation.

Approche naïve

Une manière basique de procéder (inspirée de ce message) :

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 10, 100)
y = np.sin(x)

plt.figure()
for n in range(len(x)):
    plt.cla()
    plt.plot(x[:n], y[:n])
    plt.axis([0, 10, -1, 1]) 
    plt.plot()
    plt.draw()
    plt.pause(0.0001)
    plt.clf()

Approche propre

On peut utiliser les animations fournies par matplotlib. Le code ci-dessous est adapté de cette discussion :

import numpy as np
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation

fig = plt.figure()
xmin = 0
xmax = 10
x = np.linspace(xmin, xmax, 100)
y = np.sin(x)
ymin = min(y)
ymax = max(y)
ax = plt.axes(xlim=(xmin, xmax), ylim=(ymin, ymax))
(line,) = ax.plot([], [], lw=2)

# animation function.  This is called sequentially
def update(i, x, y, line):
    line.set_data(x[:i], y[:i])
    return (line,)

ani = FuncAnimation(
    fig, update, len(x),
    fargs=[x, y, line],
    interval=25, blit=False, repeat=False
)

#ani.save("toto.gif")
input("Appuyer sur une touche afficher la courbe. Fermer la fenêtre pour continuer")
plt.show()
print("Suite...")

Généralisation de l'approche "propre" pour fonctionner dans Jupyter.

On peut généraliser les 3 dernières lignes de code pour que la faire marcher dans Jupyter.

La difficulté, c'est qu'il faut passer par un fichier temporaire (par exemple gif) ou peut être un StringIO (à tester). Quoi qu'il en soit, on ne peut pas utiliser le format svg. Et comble de malchange, Jupyter ne rend pas les animations gif (voir cette discussion). Et enfin, il faut veiller à ne pas afficher le rendu par défaut une fois la cellule évaluée (i.e, gif statique), ce qui se fait comme indiqué dans cette discussion.

Bref, une fois toutes ces idées combinées, la fin du programme devient :

import tempfile

def html(s: str):
    from IPython.display import display, HTML
    chart = HTML(s)
    # or chart = charts.plot(...)
    display(chart)

def in_ipynb() -> bool:
    try:
        from IPython import get_ipython
        return str(type(get_ipython())) == "<class 'ipykernel.zmqshell.ZMQInteractiveShell'>"
    except NameError:
        return False
    except ImportError:
        return False

def ipynb_display_gif(filename_gif: str):
    data = open(filename_gif, "rb").read()
    b64 = base64.b64encode(data).decode("ascii")
    html(f'<img src="data:image/gif;base64,{b64}" />')
    
def ipynb_display_animation(ani):
    (_, filename_gif) = tempfile.mkstemp(suffix=".gif")
    ani.save(filename_gif)
    ipynb_display_gif(filename_gif)

input("Appuyer sur une touche pour continuer")
if in_ipynb():
    ipynb_display_animation(ani)
    input("Appuyer sur une touche pour continuer")
    plt.close()
else:
    print("Fermer la fenêtre pour continuer")
print("Suite du programme")

Bonne chance

0

Merci beaucoup de vos réponse. mamiemando, votre réponse est très interressante, mais mon but n'était pas du tout de tracer une fonction. J ai juste fait un exemple d'animation avec un carré rose qui oscille, d'ou la fonction sinus. ???? Mais votre messate pourrait bien m'inspirer pour autre chose plus tard, merci beaucoup.

0
mamiemando Messages postés 33064 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 12 avril 2024 7 744
2 nov. 2022 à 14:00

Bonjour,

Pardon j'avais mal compris la question. En espérant que ceux-ci y réponde :

import turtle
import math
import time

# Demander les paramètre
shape = input("shape ? ")
assert shape in {"circle", "square"}

# Ouverture de la fenêtre
screen = turtle.Screen()
screen.bgcolor("#FFE800")
forme = turtle.Turtle()
forme.shape(shape)
forme.shapesize(10, 10)
forme.color("#800080")
for t in range(100):
    n = 10 * math.sin(t / 30) + 1
    forme.shapesize(n, n)
    time.sleep(0.01)

# Fermeture de la fenêtre
turtle.bye()
input("autre chose ? ")
print("bye bye")

En résumé, la fenêtre est créée au moment d'appeler turtle.Screen() et se ferme sur turtle.bye(). Donc il suffit d'insérer du code avant turtle.Screen() et après turtle.bye()

Bonne chance

0