Stupides fourmis et PyQt, acte 2
Retour sur la v1
Cette première version est assez lente. Et pour cause… À chaque itération on redessine toute la grille (tous les rectangles, fourmi, ou sol). Autant dire que quand on va ajouter des phéromones, ça va ramer à mort… Pour remédier à ça, il existe heureusement la classe QGraphicsScene : on ajoute des objets que l'on peut déplacer, modifier, etc. Nous, on a besoin de déplacer nos fourmis ; à chaque itération, on va redéfinir notre fourmi sur la « scene ».
La classe fourmi ne bouge pas, l'essentiel des modifications se fait sur notre GridDisplay :
display.py
Pour connaître la position des fourmis sur la grille à partir de GridDisplay, pas besoin de passer toute la grille ; on ajoutera les fourmis une à une à notre scene. Par contre il nous faut quand même connaître les dimensions de la grille. On va ajouter un canvas
sur lequel mettre notre scene
. Ce canvas
sera ajouté au layout
du widget. J'ai pris un layout
vertical pour pouvoir mettre d'éventuels boutons dessous, chose que je n'ai pas faite.
def __init__(self, dim): """ initialisation """ super(GridDisplay, self).__init__() self.dim = dim self.coordXmax = self.dim[0] self.coordYmax = self.dim[1] #central widget pour la fenêtre principale cwidget = QtGui.QWidget(self) # On met un layout sur lequel ajouter le canvas (et des futurs boutons(?)) layout = QtGui.QVBoxLayout() #le canvas qu'on ajoute au layout canvas = QtGui.QGraphicsView() layout.addWidget(canvas) #et on définit le layout du widget cwidget.setLayout(layout) #on définit une scene self.scene = QtGui.QGraphicsScene() canvas.setScene(self.scene) #on définit le remplissage et les bords self.pen = QtGui.QPen(QtGui.QColor("white")) self.brush = QtGui.QBrush(QtGui.QColor("black")) #on initialise la grille self.doBackground()
Faire le fond, c'est simple, il suffit de faire un rectangle blanc et de l'ajouter à la @<code>scene@</code> :
def doBackground(self): """initialise la grille""" w = self.size().width() h = self.size().height() _item = self.scene.addRect(0, 0, w, h, self.pen, QtGui.QBrush(QtGui.QColor("white")))
Ensuite, il va falloir une méthode pour ajouter nos rectangles-fourmis. Quand on fait un self.scene.addRect(…)
, ça nous renvoit un pointeur sur l'item ajouté à la scène. On stocke alors ces pointeurs dans une liste pour pouvoir y accéder quand il faudra les déplacer :
def addAnts(self, lAnts): """ lAnts = list of ants""" self.lAnts = lAnts self.lItems = [] w = self.size().width() h = self.size().height() x = self.coordXmax y = self.coordYmax for ant in self.lAnts: [i, j] = ant.coord item = self.scene.addRect(i*w/x,j*h/y,w/x,h/y,QtGui.QPen(QtGui.QColor("white")),QtGui.QBrush(QtGui.QColor("black"))) self.lItems.append(item)
Pour la mise à jour, il suffit de parcourir la liste de nos pointeurs de rectangles-fourmis et de les déplacer suivant leurs nouvelles coordonnées.
def animate(self): """ lAnts = list of ants""" w = self.size().width() h = self.size().height() x = self.coordXmax y = self.coordYmax for (nitem, ant) in enumerate(self.lAnts): [i, j] = ant.coord item = self.lItems[nitem] item.setRect(i*w/x, j*h/y, w/x, h/y)
simu.py
Pas grand chose qui change ici : plutôt que de passer la grille au widget central, on lui passe ses dimensions ; plus besoin de tenir à jour une grille de fourmis ; pour la méthode animate
, il suffit d'animer la grille, et de déplacer chaque fourmi.
Sources et prochaine fois
La v2 est disponible sur bitbucket.org. La prochaine fois, les fourmis laisseront des p'tites phéromones sur leur passage.
Figure 1: Vivement la suite :þ