当使用TK.TK定义许多时,将类定义的TKINTER对象放置在单个帧上



按照我从Sentdex获得的建议,我已经编码了一个多页Python/tkinter应用程序,除其他外,它在许多框架的单个框架上提供了一个时间移动的图形,居住在TK.TK。移动图的编码略有复杂,因此我选择在类上定义画布:grpcanvas(tk.canvas)。

我的问题是,这种程序结构似乎会导致画布对象出现在我的所有页面框架上!如何管理代码以使graphcanvas=GrpCanvas(HomePage)仅出现在该页面上?我已经评论了一些父母定义,以显示我尝试做的事情(并且失败)。我正在使用Python 3.4.4。

我显示了下面的代码(尽可能删除该问题):

#Avoiding canvas on all pages when pages are managed using tk.Tk
import tkinter as tk
sinewave_points=[]  #Generated by a sin function of time.
#class GrpCanvas(self, parent):
class GrpCanvas(tk.Canvas):    
    #def __init__(self, parent):
    def __init__(self, parent, controller):    
        tk.Canvas.__init__(self, height=340, width=594, bg='white')#,      x=pos_x, y=pos_y):
        self.place(x=180, y=80)
    def set_y_scale(self, sinewave_points):
        self.scale=100 #actually calculated from a scaling algorithm (adapting to amplitude of sinewave_points)
        return self.scale
    def define_graph(self, scale, sinewave_points):
        # create x-axis
        self.horizontal=self.create_line(0, 170, 594, 170, width=2) 
        for i in range(13): #used to be 26
            x = 20 + (i * 48)
            self.x_scale=self.create_text(x, 175, font=("", 6),
                                      anchor='n', text='{}'.format(((12/3) * i)-24))
        # y-axis
        self.vertical=self.create_line(20, 330, 20, 10, width=2)
        self.y_scale=self.set_y_scale(sinewave_points)
        if self.y_scale == 100:
            for i in range(21):
                self.y = int(330 - (i * (320/20))) #In fact there is an slgorithm to scale the y-axis
                #print(i, self.y)
                self.y_axis=self.create_text(17, (self.y), font=("", 6), anchor='e',
                                text='{}'.format(int((((200/320)*(320/20)) * i)-
                                100)))

        for i in range(len(sinewave_points)):                    
            self.x, self.y = (i+20) , int(-1*self.scale*sinewave_points[i])+ 170
            self.history=self.create_oval(self.x - 1, self.y - 1, self.x + 1,
                                      self.y + 1, width=0, fill='purple')

class Moving_Sinewave(tk.Tk):
    def __init__(self, *args, **kwargs):        
        #Initialising Tkinter    
        tk.Tk.__init__(self, *args, **kwargs)
        tk.Tk.wm_title(self, 'Sinewave Moving Plotter')
        tk.Tk.geometry(self, '800x480')#This is the size of the screen (in pixels)       
        container = tk.Frame(self)
        container.pack(fill='both', expand= True)#(side="top", fill="both", expand = True)
        container.grid_rowconfigure (0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        self.frames = {}
        for F in (HomePage,                 
              SystemConfigPage,                   
              ConfigAlarmsPage):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
            frame.configure(background= 'ivory2'),
        self.show_frame(HomePage)
    def show_frame(self, cont):       
        frame=self.frames[cont]
        frame.tkraise()

class HomePage(tk.Frame):
    def __init__(self, parent, controller):
        self.controller=controller
        tk.Frame.__init__(self, parent)
        global time1, time2, time4, time5
        sysconfigbutton=tk.Button(self, text= 'SystemnConfiguration',        
                              command=lambda: controller.show_frame(SystemConfigPage),
                              height=2, width=12)
        sysconfigbutton.place(x=20, y=80)
        #graphcanvas=GrpCanvas(tk.Frame)            #works with:    class GrpCanvas(tk.Canvas):    
                                                            #def __init__(self, parent):
        #graphcanvas=GrpCanvas(HomePage)            #works with:    class GrpCanvas(tk.Canvas):    
                                                            #def    __init__(self, parent):
        #graphcanvas=GrpCanvas(HomePage(tk.Frame))
        graphcanvas=GrpCanvas(HomePage, controller.tk)# works with: class GrpCanvas(tk.Canvas):    
                                                    #def __init__(self, parent, controller):
        graphcanvas.define_graph(graphcanvas.set_y_scale(sinewave_points), sinewave_points)
    # This actually plots the points
class SystemConfigPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        configalarmsbutton=tk.Button(self, text= 'ConfigurenAlarms',
                            command=lambda: controller.show_frame(ConfigAlarmsPage),                                 
                            height=2, width=12)
        configalarmsbutton.place(x=20, y=180)
class ConfigAlarmsPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        backbutton=tk.Button(self, text= 'Back',
                         command=lambda: controller.show_frame(HomePage),
                               height=2, width=12)
        backbutton.place(x=20, y=380)

app = Moving_Sinewave()             
app.mainloop()

GrpCanvas的第一个参数需要是出现画布的父窗口。在这种特定情况下,您应该使用self,因为您希望它在主页中,并且正在创建它作为创建HomePage的一部分:

graphcanvas=GrpCanvas(self, controller.tk)

您还需要将此参数传递到父母类的__init__,您要忽略了。要解决这个问题,请更改此问题:

tk.Canvas.__init__(self, height=340, ...)

...对此:

tk.Canvas.__init__(self, parent, height=340, ...)

发生的事情是,由于您没有通过父,因此小部件将root窗口用作默认值。而且,由于您使用的是place,并且由于该小部件是最后创建的(因此是堆叠顺序的顶部),所以它出现在所有页面的顶部。

最新更新