Interface graphique python turtle

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

  1. 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
    1. Modérateur

      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
      1. 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
        1. Modérateur

          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