web-dev-qa-db-fra.com

Comment créer des fenêtres enfants avec Python tkinter?

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?

12
Chenxiao

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()
41
Bryan Oakley