尝试在 Windows 中使用 python 冻结 tkinter 中的部分滚动区域

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

我在Windows中使用Python 3.11.9。

这是我的最低可验证代码:

import tkinter as tk

class Table(tk.Frame):
    def __init__(self, master, header_labels:tuple,*args, **kwargs):
        tk.Frame.__init__(self, master, *args, **kwargs)
        # configuration for all Labels
        # easier to maintain than directly inputting args
        self.lbl_cfg = {
            'master'     : self,
            'foreground' : 'blue',
            'relief'     : 'solid',
            'font'       : 'Arial 20 bold',
            'padx'       : 5,
            'pady'       : 0,
            'bd'         : 1,
            'bg'         : 'white',
        }
        self.headers = []
        self.rows    = []
        for col, lbl in enumerate(header_labels):
            self.grid_columnconfigure(col, weight=1)
            # make and store header
            (header := tk.Label(text=lbl, **self.lbl_cfg)).grid(row=0, column=col, sticky='nswe')
            self.headers.append(header)
            
    def add_row(self, desc:str, rate:int, quantity:int, amt:int) -> None:
        print('adding a row to table')
        self.rows.append([])
        for col, lbl in enumerate( ((str(len(self.rows))),desc, rate, quantity, amt) ):
            (entry := tk.Label(text=lbl, **self.lbl_cfg)).grid(row=len(self.rows), column=col, sticky='nswe')
            self.rows[-1].append(entry)

class Application(tk.Tk):
    def __init__(self, title:str="Bill generation", x:int=0, y:int=0, **kwargs):
        tk.Tk.__init__(self)
        self.title(title)
        self.config(**kwargs)
#DEFAULTS
        
#Fixed Entries
        header_labels = ('\u2193','Description','Rate','Quantity','Amt','\u2191')

#KEYBOARD SHORTCUTS
#FONT SETTINGS
        self.gui_lbl_look = {
            'foreground' : 'black',
            'relief'     : 'flat',
            'font'       : 'Arial 18 bold',
            'padx'       : 0,
            'pady'       : 0,
            'borderwidth': 1,
        }
        self.gui_btn_look = {
            'foreground' : 'red',
            'relief'     : 'groove',
            'font'       : 'Arial 18 bold',
            'padx'       : 0,
            'pady'       : 0,
        }
        self.gui_entry_look = {
            'foreground' : 'blue',
            'font'       : 'Arial 18 bold',
            'highlightbackground'   :"black",
            'highlightthickness'    : 2,
            'highlightcolor'        :"blue",
            'insertbackground'      :"blue",
            'insertwidth'           :3,
        }
        self.gui_total_lbl_look = {
            'foreground' : 'green',
            'relief'     : 'solid',
            'font'       : 'Arial 18 bold',
        }
#Text input check
#GUI 
    #bill number and print button
# Second row 
        self.second_row_frame=tk.Frame(self)
        self.second_row_frame.grid(column=0,row=1,sticky='W',pady=5)
# Goods return field
        self.lbl_return=tk.Label(self.second_row_frame,text="GR:",**self.gui_lbl_look)
        self.lbl_return.grid(column =0, row =0)
        self.return_str=tk.StringVar()
        self.return_value=tk.Entry(self.second_row_frame,width=5,textvariable=self.return_str,**self.gui_entry_look)
        self.return_value.grid(column=1,row=0,padx=(0,5))
#description field
        self.default_txt_for_desc=tk.StringVar()
        self.default_txt_for_desc.set("PCS")
        self.txt_desc=tk.Entry(self.second_row_frame,width=10,textvariable=self.default_txt_for_desc,**self.gui_entry_look)
        self.txt_desc.grid(column=2,row=0)
# rate field
        self.lbl_rate=tk.Label(self.second_row_frame,text="Rate:",**self.gui_lbl_look)
        self.lbl_rate.grid(column=3,row=0,padx=(5,0))
        self.rate_str=tk.StringVar() 
        self.txt_rate=tk.Entry(self.second_row_frame,width=4,textvariable=self.rate_str,**self.gui_entry_look)
        self.txt_rate.grid(column=4,row=0)
# quantity field
        self.lbl_qty=tk.Label(self.second_row_frame,text="Qty:",**self.gui_lbl_look)
        self.lbl_qty.grid(column=5,row=0,padx=(5,0))
        self.qty_str=tk.StringVar() 
        self.txt_qty=tk.Entry(self.second_row_frame,width=3,textvariable=self.qty_str,**self.gui_entry_look)
        self.txt_qty.grid(column=6,row=0)
#Item amount
        self.lbl_amt=tk.Label(self.second_row_frame,text="Amount:",**self.gui_lbl_look,bd=1,anchor="e",justify="right")
        self.lbl_amt.grid(column=7,row=0,padx=(5,0))
        self.txt_amt=tk.Label(self.second_row_frame,text='0',width=5,**self.gui_lbl_look,bd=1,anchor="w",justify="left")
        self.txt_amt.grid(column=8,row=0)
#Add to table button
        self.btn_add=tk.Button(self.second_row_frame,text="Add",command=self.clicked,**self.gui_btn_look)
        self.btn_add.grid(column=9,row=0,padx=5)
# Third row entry Table
        self.content_frame=tk.Frame(self,highlightbackground="black",highlightthickness=1)
        self.content_frame.grid(column=0,row=2,sticky='news')
        self.canvas=tk.Canvas(self.content_frame,bg='sky blue')
        scrollbar=tk.Scrollbar(self.content_frame,orient="vertical",command=self.canvas.yview,width=50)
        self.canvas.configure(yscrollcommand=scrollbar.set)
        self.table_frame=tk.Frame(self.canvas)
        self.table_frame.grid(column=0,row=0,sticky='news')
        self.table_frame.bind("<Configure>",lambda e:self.canvas.configure(scrollregion=self.canvas.bbox("all")))
        self.content_frame.columnconfigure(0,weight=2)
        self.content_frame.rowconfigure(0,weight=2)
        self.canvas.create_window((0, 0),window=self.table_frame,anchor="nw")
        self.frame_id=self.canvas.create_window((0,0),window=self.table_frame,anchor="nw")
        self.canvas.grid(row=0,column=0,sticky="nswe")
        self.canvas.bind_all("<MouseWheel>",self._on_mousewheel)
        scrollbar.grid(row=0,column=1,sticky="ns")
        self.table_frame.trial_var=0
        self.table = Table(self.table_frame,header_labels)
        self.table.grid(row=0,column=0,sticky='nswe')
#virtual keyboard
        self.keyboard_frame=tk.Frame(self,highlightbackground="black",highlightthickness=1)
        self.keyboard_frame.grid(column=0,row=2,sticky='se',padx=(10,55))
        self.info_label=tk.Label(self,text=" New bill:space \n Cancel:x \n GR:F1 \n Rate:F2 \n Qty:F3 \n Print:F10 ",**self.gui_total_lbl_look)
        self.info_label.grid(column=0,row=2,sticky='ne',padx=(10,55))
        self.grid_rowconfigure(2, weight=1)
        self.grid_columnconfigure(2, weight=1)
        for numbers in range(1,11):
            self.add_number_button=tk.Button(self.keyboard_frame,text=str(numbers%10),**self.gui_btn_look)
            self.add_number_button.grid(column=int(numbers-1)%3,row=int((numbers-1)/3))
        self.clear_button=tk.Button(self.keyboard_frame,text='Del',**self.gui_btn_look)
        self.clear_button.grid(column=1,row=3,columnspan=2,sticky='e')
        self.enter_button=tk.Button(self.keyboard_frame,text='Enter',**self.gui_btn_look)
        self.enter_button.grid(column=0,row=4,columnspan=3,sticky='')
#maximizing table cell
        self.grid_columnconfigure(0, weight=1)
#Total quantity amount and balance
        self.totals_frame=tk.Frame(self)
        self.totals_frame.grid(column=0,row=3,sticky='')
        self.lbl_tot_qty=tk.Label(self.totals_frame,text="Total Quantity:",**self.gui_total_lbl_look)
        self.lbl_tot_qty.grid(column=0,row=0,padx=5)
        self.lbl_tot_amt=tk.Label(self.totals_frame,text="Total Amount:",**self.gui_total_lbl_look)
        self.lbl_tot_amt.grid(column=1,row=0,padx=5)
        self.lbl_bal=tk.Label(self.totals_frame,text="Balance:",**self.gui_total_lbl_look)
        self.lbl_bal.grid(column=2,row=0,padx=5)
        
        # update so we can get the current dimensions           
        self.update_idletasks()
        self.state('zoomed')
        #FOR LINUX self.attributes('-zoomed',True)
        # test

    def _on_mousewheel(self,event):
        print('scroll in table')
        self.canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")

    def clicked(self):
        text_qty=(self.txt_qty.get()).lstrip('0')
        text_rate=(self.txt_rate.get()).lstrip('0')
        item_amt=int(text_rate)*int(text_qty)
        print('adding to table')
        desc=self.txt_desc.get().upper()
        self.table.add_row(desc,int(text_rate),int(text_qty),item_amt)
        return

if __name__ == "__main__":
    Application(title="Bill printing app").mainloop()

在此代码中,当您在 GR 、费率和数量条目中输入数字,然后按添加按钮,则会将一行添加到表中。
现在我的问题是,当行数超过屏幕并且我们向下滚动时,我希望表格标题(描述、费率数量、amt)应保留在其位置。
你能帮我吗?

这是滚动条在顶部时的截图 window screenshot when scrollbar is at top

这是滚动条在底部时的截图 window screenshot when scrollbar is at bottom

我已经尝试发布相关代码,您可以轻松地在您的终端上运行。
如果您需要任何其他详细信息,请告诉我。
谢谢。

tkinter
1个回答
0
投票

您不能将标题放在滚动的画布上方的不同框架中吗?当您滚动浏览表格内容时,这应该使表格标题保持在适当的位置。

© www.soinside.com 2019 - 2024. All rights reserved.