如何用Python tkinter创建子窗口?

问题描述:

我正在使用Python 3.3和tkinter来制作一个用于行人逃离模拟的GUI界面。如何用Python tkinter创建子窗口?

我写了两个模拟程序,它们运行良好。但是,我试图从我的主应用程序调用它们时卡住了。我希望模拟窗口出现在单独的窗口中(创建主窗口的子窗口)。

#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() 

如何从我的主应用程序与tkinter启动子窗口?

+0

示例代码应与[最小的完整可验证的示例]更换(https://*.com/help/ MCVE)。这是相当漫长的,而且大多与具体问题无关。 – 2018-02-15 16:02:06

通过创建Toplevel的实例来创建子窗口。有关更多信息,请参见http://effbot.org/tkinterbook/toplevel.htm

下面是一个例子,可以让你通过点击一个按钮,创建新窗口:

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()