J'utilise Python 3.3 et tkinter pour créer une interface graphique pour une simulation de fuite des piétons.
J'ai écrit deux programmes de simulation et ils ont bien fonctionné. Cependant, je me suis retrouvé coincé en essayant de les appeler depuis mon application principale. Je souhaite que la fenêtre de simulation apparaisse dans une fenêtre distincte (créez une fenêtre enfant de la fenêtre principale).
#flee_GUI.py
#!/usr/bin/env python
import tkinter
class MenuBar(tkinter.Menu):
def __init__(self,parent):
tkinter.Menu.__init__(self,parent)
###File###
fileMenu = tkinter.Menu(self, tearoff=False)
self.add_cascade(label="File",underline=0, menu=fileMenu)
fileMenu.add_command(label='Open',underline=1)
fileMenu.add_separator()
fileMenu.add_command(label="Exit", underline=1, command=self.quit)
###Run###
runMenu=tkinter.Menu(self,tearoff=False)
self.add_cascade(label='Run',underline=1,menu=runMenu)
runMenu.add_command(label='Open Bounary Model',underline=1,command=runModel1)
class Frame(tkinter.Tk):
def __init__(self,parent):
tkinter.Frame.__init__(self,parent)
self.parent=parent
def runModel1():
from drawcanvas_Alpha_7_0_open_border import cell
I=cell(None)
class App(tkinter.Tk):
def __init__(self,parent):
tkinter.Tk.__init__(self,parent)
self.parent=parent
runModel1()
menubar=MenuBar(self)
self.config(menu=menubar)
if __name__=='__main__':
app=App(None)
app.mainloop()
#drawcanvas_Alpha_7_0_open_border.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#Run this by python3.x.
#If you are using Python2.x,be aware of the difference such as print,Tkinter and tkinter,etc.
#from tkinter import *
import tkinter
import random
#class cell(Frame):
class cell(tkinter.Tk):
def __init__(self,parent):
tkinter.Tk.__init__(self,parent)
self.parent=parent
self.channel_length=40#aisle length (1 unit for 10 pixel)
self.channel_width=40#aisle width
self.Origin_x=0
self.Origin_y=0
self.pixel_unit=10
self.speed=100
self.alltime=0
self.PN=100#Number of pedestrian
self.Pu=0.1
self.Pd=0.9#probability of going down if the right side were occupied
self.window_width=self.Origin_x+self.channel_length*self.pixel_unit
self.window_height=self.Origin_y+self.channel_width*self.pixel_unit+2*self.pixel_unit
self.canvas=tkinter.Canvas(
self.parent,width=self.window_width,height=self.window_height,bg='lightblue')
self.Ped_x=[]
self.Ped_y=[]
self.block_flag=[]
self.block_occupy=[]
self.draw_canvas()
self.draw_grid()
self.draw_architecture()
self.draw_pedestrian_init()
self.draw_pedestrian()
def draw_canvas(self):
self.canvas.pack()
def destroy_canvas(self):
self.canvas.destroy()
def destroy_architecture(self):
pass
def draw_grid(self):
for i in range(2,self.channel_width+1):
self.draw_line(0,i,self.channel_length,i)
for i in range(1,self.channel_length):
self.draw_line(i,0,i,self.channel_width+1)
def draw_line(self,x0,y0,x1,y1,linedash=1):
self.canvas.create_line(
self.Origin_x+x0*self.pixel_unit,
self.Origin_y+y0*self.pixel_unit,
self.Origin_x+x1*self.pixel_unit,
self.Origin_y+y1*self.pixel_unit,dash=linedash)
def draw(self,x0,y0,x1,y1,color='black'):
self.canvas.create_rectangle(
self.Origin_x+x0*self.pixel_unit,
self.Origin_y+y0*self.pixel_unit,
self.Origin_x+x1*self.pixel_unit,
self.Origin_y+y1*self.pixel_unit,
fill=color)
for i in range(y0,y1):
for j in range(x0,x1):
self.block_occupy[i][j]=1
#print(j,i)
def draw_architecture(self):
for i in range(0,(self.channel_width+1)+1):
self.block_occupy.append([])
for j in range(0,self.channel_length):
self.block_occupy[i].append(0)
self.draw(0,0,self.channel_length,1)
self.draw(0,self.channel_width+1,self.channel_length,self.channel_width+2)
self.draw(30,1,31,int(self.channel_width/2-1),'red')
#self.draw(30,int(self.channel_width/2+1),31,self.channel_width+1,'red')
def draw_pedestrian_init(self):
Ped_count=0
while Ped_count<self.PN:
self.Ped_x.append(
int(random.randrange(
self.Origin_x,self.Origin_x+30*self.pixel_unit)/self.pixel_unit)*self.pixel_unit)
self.Ped_y.append(
int(random.randrange(
self.Origin_y+self.pixel_unit,self.Origin_y+(self.channel_width+1)*self.pixel_unit)/self.pixel_unit)*self.pixel_unit)
tmp_x=int((self.Ped_x[Ped_count]-self.Origin_x)/self.pixel_unit)
tmp_y=int((self.Ped_y[Ped_count]-self.Origin_y)/self.pixel_unit)
if self.block_occupy[tmp_y][tmp_x]==1:
self.Ped_x.pop()
self.Ped_y.pop()
else:
self.block_occupy[tmp_y][tmp_x]=1
Ped_count=Ped_count+1
self.block_flag=[self.canvas.create_rectangle(self.Ped_x[i],self.Ped_y[i],
self.Ped_x[i]+self.pixel_unit,self.Ped_y[i]+self.pixel_unit,fill='green') for i in range(0,self.PN)]
def draw_pedestrian(self):
for i in range(0,self.PN):
self.canvas.delete(self.block_flag[i])
#print(self.block_occupy)
#count_f=self.PN
for i in range(0,self.PN):
if self.Ped_x[i]>self.Origin_x+(self.channel_length-1)*self.pixel_unit-1:
#self.Ped_x[i]=self.Ped_x[i]-self.channel_length*self.pixel_unit
dummy_x=int((self.Ped_x[i]-self.Origin_x)/self.pixel_unit)
dummy_y=int((self.Ped_y[i]-self.Origin_y)/self.pixel_unit)
self.block_occupy[dummy_y][dummy_x]=0
#count_f=self.PN-1
self.Ped_x[i]=-1
self.Ped_y[i]=-1
temp_block_flag1=[]
temp_block_flag2=[]
for i in range(0,self.PN):
if self.Ped_x[i]!=-1:
temp_block_flag1.append(self.block_flag[i])
else:
temp_block_flag2.append(self.block_flag[i])
self.block_flag=temp_block_flag1
for i in range(0,len(temp_block_flag2)):
self.canvas.delete(temp_block_flag2[i])
self.Ped_x=[self.Ped_x[i] for i in range(0,self.PN) if self.Ped_x[i]!=-1]
self.Ped_y=[self.Ped_y[i] for i in range(0,self.PN) if self.Ped_y[i]!=-1]
self.PN=len(self.Ped_x)
for i in range(0,self.PN):
print(self.PN,i,len(self.Ped_x))
tmp_x=int((self.Ped_x[i]-self.Origin_x)/self.pixel_unit)
tmp_y=int((self.Ped_y[i]-self.Origin_y)/self.pixel_unit)
if self.block_occupy[tmp_y][tmp_x+1]==0:
self.block_occupy[tmp_y][tmp_x]=0
self.block_occupy[tmp_y][tmp_x+1]=1
self.Ped_x[i]=self.Ped_x[i]+self.pixel_unit
Elif (self.block_occupy[tmp_y+1][tmp_x]==0
and self.block_occupy[tmp_y-1][tmp_x]==0):#The right side is occupied,while the up and down side is free
if random.uniform(0,1)<self.Pd:#go down
self.block_occupy[tmp_y][tmp_x]=0
self.block_occupy[tmp_y+1][tmp_x]=1
self.Ped_y[i]=self.Ped_y[i]+self.pixel_unit
else:#go up
self.block_occupy[tmp_y][tmp_x]=0
self.block_occupy[tmp_y-1][tmp_x]=1
self.Ped_y[i]=self.Ped_y[i]-self.pixel_unit
Elif (self.block_occupy[tmp_y+1][tmp_x]==1 #the up side is occupied,while the down side is free
and self.block_occupy[tmp_y-1][tmp_x]==0):
self.block_occupy[tmp_y][tmp_x]=0
self.block_occupy[tmp_y-1][tmp_x]=1
self.Ped_y[i]=self.Ped_y[i]-self.pixel_unit
Elif (self.block_occupy[tmp_y+1][tmp_x]==0 #the up side is free,while the down side is occupied
and self.block_occupy[tmp_y-1][tmp_x]==1):
self.block_occupy[tmp_y][tmp_x]=0
self.block_occupy[tmp_y+1][tmp_x]=1
self.Ped_y[i]=self.Ped_y[i]+self.pixel_unit
#print(self.block_occupy)
self.block_flag=[self.canvas.create_rectangle(self.Ped_x[i],self.Ped_y[i],
self.Ped_x[i]+self.pixel_unit,self.Ped_y[i]+self.pixel_unit,fill='green') for i in range(0,self.PN)]
self.alltime+=1
self.after(self.speed,self.draw_pedestrian)
if self.PN==0:
print("Fleeing complete!,total time:",self.alltime)
self.destroy_canvas()
if __name__=='__main__':
Io=cell(None)
Io.mainloop()
Comment puis-je lancer une fenêtre enfant à partir de mon application principale avec tkinter?
Vous créez des fenêtres enfants en créant des instances de Toplevel
. Voir http://effbot.org/tkinterbook/toplevel.htm pour plus d'informations.
Voici un exemple qui vous permet de créer de nouvelles fenêtres en cliquant sur un bouton:
import Tkinter as tk
class MainWindow(tk.Frame):
counter = 0
def __init__(self, *args, **kwargs):
tk.Frame.__init__(self, *args, **kwargs)
self.button = tk.Button(self, text="Create new window",
command=self.create_window)
self.button.pack(side="top")
def create_window(self):
self.counter += 1
t = tk.Toplevel(self)
t.wm_title("Window #%s" % self.counter)
l = tk.Label(t, text="This is window #%s" % self.counter)
l.pack(side="top", fill="both", expand=True, padx=100, pady=100)
if __name__ == "__main__":
root = tk.Tk()
main = MainWindow(root)
main.pack(side="top", fill="both", expand=True)
root.mainloop()