网格管理器未在左上角放置框架

问题描述 投票:0回答:1

我正在调试可滚动框架,以容纳一个框架,该框架可以增大到更大的尺寸,然后减小(包含的小部件被销毁,并且放回了较小的数字)。框架是:frame.grid(column = 0,row = 0,sticky ='nw')。但是,较小的框架有点放在画布的中间。如果运行此示例,则最初将获得9个复选按钮和条目的列表。如果按显示更多按钮,您将看到所有30个按钮/条目,然后按显示较少的按钮,您将看到原始框架,但它不在画布的西北角。

import tkinter as tk
from tkinter import ttk
import os
import inspect
import functools
import sys

class ScrollableFrame:
    # https://blog.tecladocode.com/tkinter-scrollable-frame
    def __init__(self,container):
        self.container = container
        self.top_frame = tk.Frame(container,height=2)
        self.top_frame.configure(bg='gray15')

    # create a frame to hold the Canvas andscrollbars

        self.canvas = tk.Canvas(container,borderwidth=5)
        self.canvas.configure(bg = 'orange')

    #self.canvas.pack_propagate(False)

        self.content_frame = tk.Frame(self.canvas, bg = 'yellow')    
    #self.content_frame.grid_propagate(True)
    # create a vertical scrollbar linked to the canvas 
        self.scrollbar = ttk.Scrollbar(self.canvas, orient="vertical", command=self.canvas.yview)
        self.canvas.configure(yscrollcommand=self.scrollbar.set) # again scrollbar.set is a provided function
        self.scrollbar.config(command=self.canvas.yview)

        self.xscrollbar = ttk.Scrollbar(self.canvas, orient = 'horizontal', command=self.canvas.xview)
        self.canvas.configure(xscrollcommand=self.xscrollbar.set) 
        self.xscrollbar.config(command=self.canvas.xview)


    # before we are done we need to put buttons into ScrollableFame, row 0
    # and populate the content_frame with widgets
    # after this has been done, the bounding box must be created 


        container.bind(
            "<Configure>",
            lambda e: self.canvas.configure(
            scrollregion=self.canvas.bbox("all")
            )
        )

    def finish(self):
        self.container.config(bg = 'lightgreen')
        self.top_frame.pack(side=tk.TOP,fill=tk.BOTH,expand=False)
    #self.content_frame.pack(side=tk.TOP,fill = tk.BOTH,expand=False)
        self.content_frame.grid(column=0,row=0,sticky='nw',ipadx = 5,ipady=5)
        self.canvas.create_window((0,0), window=self.content_frame) 

        self.canvas.pack(side=tk.TOP,fill=tk.BOTH,expand=True,ipady=10)
        self.canvas.configure(scrollregion=self.canvas.bbox('all'))

        self.canvas.pack_propagate(False)

        self.scrollbar.pack(fill='both',side='right',expand='false')
        self.xscrollbar.pack(fill='both',side='bottom',expand='false')
    #self.container.grid(column=0,row=0,sticky='nsew')
    #self.container.rowconfigure(0,weight=1)
    #self.container.columnconfigure(0,weight=1)
        self.canvas.update_idletasks()
        self.canvas.yview_moveto(0)
        self.canvas.xview_moveto(0)

class DisplayKeys(tk.Frame):
    def __init__(self,parent,*args,**kwargs) :
        tk.Frame.__init__(self,parent,*args,**kwargs)
        self.keys_ = [f'display{i}' for i in range(30)]
        self._showless = False
        self._checkbuttons_initialized = None
        self.scrollable_frame = ScrollableFrame(parent)
        self._label = tk.Label(self.scrollable_frame.top_frame,
                           text = "Key List",font = LARGE_FONT)
        self._label.grid(column=0,row=0)

        self._sequence = [1,2,3,29,5,7,21,15,6]
        self._showbutton = tk.Button(self.scrollable_frame.top_frame, 
                       text='Show More',
                       command=lambda: 
                       self._showbutton_action())

        self._showbutton.grid(column=2,row=0,padx=10,sticky=tk.N)
        self._update_checkbuttons(
                  self.scrollable_frame.content_frame,self._sequence )
    #self.scrollable_frame.finish()


    def _update_checkbuttons(self,frame,seq):
    #print(*seq)
        if self._checkbuttons_initialized != None :
            for widget in self.scrollable_frame.content_frame.winfo_children() :
                widget.destroy()
        self._checkbuttons_initialized = True     
        self.checkVars = []
        self.txtVars = []
        searchVar = "Search"
        self._checkbuttons = []

        for i,place in enumerate(seq) :
            bv = tk.BooleanVar()
            tvar = tk.StringVar()
            dn = self.keys_[place]
            ck = tk.Checkbutton(frame,text=dn,variable=bv)
            ck.grid(column=0,row=i,sticky='nw')
            self._checkbuttons.append(ck)
            self.checkVars.append(bv)
            txt = tk.Entry(frame,width = 30, textvariable = tvar)
            txt.bind('<Return>',self._cmgo)
            txt.grid(column = 1,row = i,sticky="nw")
        #txt.rowconfigure(0,minsize=400,weight = 1)
        #txt.columnconfigure(0,weight=1)
            self.txtVars.append(tvar)
        self.scrollable_frame.finish()
    #self.scrollable_frame.canvas.pack()
    #tk.Label(frame,height=1,bg = 'skyblue').grid(column=0,row=len(seq)+1)
    #self.scrollable_frame.canvas.configure(scrollregion=self.scrollable_frame.canvas.bbox("all") ) 

    def _cmgo(self):
        pass

    def _showbutton_action(self):

        if not self._showless :
            self._sequence = range(len(self.keys_))           
            self._showbutton.configure( text = "Show Less")
        #self._showbutton.grid(column=2,row=0,sticky=tk.W)
            self._showless = True

        else :            
            self._showbutton.configure(text = "Show More")
        #self._showbutton.grid(column=2,row=0,sticky=tk.W)
            self._showless = False
            self._sequence = [1,2,3,29,5,7,21,15,6]


        self._update_checkbuttons(
               self.scrollable_frame.content_frame,self._sequence) 

if __name__=="__main__" :
    LARGE_FONT= ("Verdana", 12)
    DISPLAY_KEYS_GEOMETRY='350x450'
    root = tk.Tk()
    show = DisplayKeys(root)
    show.pack()
    root.mainloop()
tkinter frames scrollable
1个回答
0
投票

我真的很明白我的例子太大了。我有一个解决方法,我将显示。唯一的优点是它显示了定义类的价值,使破坏和替换可滚动框架变得容易。解决方案是销毁整个可滚动框架并重建它。我不明白为什么:self.content_frame.grid(列= 0,行= 0,粘性='nw',ipadx = 5,ipady = 5)第53行不起作用,但是这种解决方法可以让我继续前进。抱歉,如果有人在这个问题上花费了时间。

import tkinter as tk
from tkinter import ttk
import os
import inspect
import functools
import sys

class ScrollableFrame:
    # https://blog.tecladocode.com/tkinter-scrollable-frame
    def __init__(self,container):
        self.container = container
        self.top_frame = tk.Frame(container,height=2)
        self.top_frame.configure(bg='gray15')

        # create a frame to hold the Canvas andscrollbars

        self.canvas = tk.Canvas(container,borderwidth=5)
        self.canvas.configure(bg = 'orange')

        self.content_frame = tk.Frame(self.canvas, bg = 'yellow')    
        #self.content_frame.grid_propagate(True)
        # create a vertical scrollbar linked to the canvas 
        self.scrollbar = ttk.Scrollbar(self.canvas, orient="vertical", command=self.canvas.yview)
        self.canvas.configure(yscrollcommand=self.scrollbar.set) # again scrollbar.set is a provided function
        self.scrollbar.config(command=self.canvas.yview)

        self.xscrollbar = ttk.Scrollbar(self.canvas, orient = 'horizontal', command=self.canvas.xview)
        self.canvas.configure(xscrollcommand=self.xscrollbar.set) 
        self.xscrollbar.config(command=self.canvas.xview)


        # before we are done we need to put buttons into ScrollableFame, row 0
        # and populate the content_frame with widgets
        # after this has been done, the bounding box must be created 


        container.bind(
            "<Configure>",
            lambda e: self.canvas.configure(
                scrollregion=self.canvas.bbox("all")
            )
        )

    def destroy(self):
        self.top_frame.destroy()
        self.canvas.destroy()

    def finish(self):
        self.container.config(bg = 'lightgreen')
        self.top_frame.pack(side=tk.TOP,fill=tk.BOTH,expand=False)
        #self.content_frame.pack(side=tk.TOP,fill = tk.BOTH,expand=False)
        self.content_frame.grid_rowconfigure(0,weight=1)
        self.content_frame.grid(column=0,row=0,sticky='nw',ipadx = 5,ipady=5)
        self.canvas.create_window((0,0), window=self.content_frame) 
        self.canvas.pack(side=tk.TOP,fill=tk.BOTH,expand=False,ipady=10)
        self.scrollbar.pack(fill='both',side='right',expand='false')
        self.xscrollbar.pack(fill='both',side='bottom',expand='false')
        self.canvas.update_idletasks()
        self.canvas.yview_moveto(0)
        self.canvas.xview_moveto(0)

class DisplayKeys(tk.Frame):
    def __init__(self,parent,*args,**kwargs) :
        tk.Frame.__init__(self,parent,*args,**kwargs)
        self.keys_ = [f'display{i}' for i in range(30)]
        self.parent = parent
        self._showless = False
        #self._checkbuttons_initialized = None
        self.scrollable_frame = ScrollableFrame(parent)
        self._label = tk.Label(self.scrollable_frame.top_frame,
                               text = "Key List",font = LARGE_FONT)
        self._label.grid(column=0,row=0)

        self._sequence = [1,2,3,29,5,7,21,15,6]
        self._showbutton = tk.Button(self.scrollable_frame.top_frame, 
                           text='Show More',
                           command=lambda: 
                           self._showbutton_action())

        self._showbutton.grid(column=2,row=0,padx=10,sticky=tk.N)
        self._update_checkbuttons(self.scrollable_frame.content_frame,self._sequence )

    def _update_checkbuttons(self,frame,seq):
        #print(*seq)
    #    self._checkbuttons_initialized = True     
        self.checkVars = []
        self.txtVars = []
        searchVar = "Search"
        self._checkbuttons = []

        for i,place in enumerate(seq) :
            bv = tk.BooleanVar()
            tvar = tk.StringVar()
            dn = self.keys_[place]
            ck = tk.Checkbutton(frame,text=dn,variable=bv)
            ck.grid(column=0,row=i,sticky='w')
            ck.grid_rowconfigure(0,weight = 1)
            self._checkbuttons.append(ck)
            self.checkVars.append(bv)
            txt = tk.Entry(frame,width = 30, textvariable = tvar)
            txt.bind('<Return>',self._cmgo)
            txt.grid(column = 1,row = i,sticky="nw")
            txt.grid_rowconfigure(1,weight=2)
            #txt.grid_rowconfigure(0,minsize=400,weight = 1)
            #txt.grid_columnconfigure(0,weight=1)
            self.txtVars.append(tvar)

        self.scrollable_frame.finish()

    def _cmgo(self):
        pass

    def _showbutton_action(self):

        if not self._showless :
            self._sequence = range(len(self.keys_))           
            button_text = "Show Less"
            #self._showbutton.grid(column=2,row=0,sticky=tk.W)
            self._showless = True

        else :            
            button_text = "Show More"
            #self._showbutton.grid(column=2,row=0,sticky=tk.W)
            self._showless = False
            self._sequence = [1,2,3,29,5,7,21,15,6]

        self.scrollable_frame.destroy()
        self.scrollable_frame = ScrollableFrame(self.parent)
        self._label = tk.Label(self.scrollable_frame.top_frame,
                               text = "Key List",font = LARGE_FONT)
        self._label.grid(column=0,row=0)

        self._showbutton = tk.Button(self.scrollable_frame.top_frame, 
                           text=button_text,
                           command=lambda: 
                           self._showbutton_action())

        self._showbutton.grid(column=2,row=0,padx=10,sticky=tk.N)

        self._update_checkbuttons(self.scrollable_frame.content_frame,self._sequence) 

if __name__=="__main__" :
    LARGE_FONT= ("Verdana", 12)
    DISPLAY_KEYS_GEOMETRY='350x450'
    root = tk.Tk()
    show = DisplayKeys(root)
    show.pack()
    root.mainloop()
© www.soinside.com 2019 - 2024. All rights reserved.