XY滚动区域的Tkinter非Y滚动标题



我正在寻找一种方法,为一个可以在X方向上滚动但不能在Y方向上滚动的表格保留一个静态标题,同时为一个既可以在X上滚动又可以在Y上滚动的表保留一个标题。

对于数据列=[","](列表(和行=[{":",">

代码:

def table_scroll_Y(self, *args):
self.table_title.yview
self.table_data.yview
def build_table(self, cols, data):
for child in self.tablebase.winfo_children(): # Clear existing table
child.pack_forget()
child.destroy()
colour1 = "#EEEEEE" # sets title colour
rheight = 1 # sets row height
rowsize = []
#Note: self.tku.cFrame(**kwrds) =  Frame(*args) and frame.pack(*args)
layout1=self.tku.cFrame(self.tablebase, side=LEFT,  fill=BOTH, expand=1, bg="white") #split between table area and scroll bar for fixed Y scroll
self.Vscroll = Scrollbar(self.tablebase, orient="vertical")
self.Vscroll.pack(side=RIGHT, fill=Y)
layout2 = self.tku.cFrame(layout1, side=TOP, fill=BOTH, expand=1, bg="white") #split between table and bottom scroll for fixed X scroll
self.Hscroll = Scrollbar(layout1, orient="horizontal")
self.Hscroll.pack(side=BOTTOM, fill=X)
self.table_title = Canvas(layout2, bg="red", highlightthickness=0, height=10) #X scroll area for Column titles
self.table_data = Canvas(layout2, bg="blue", highlightthickness=0, yscrollcommand=self.Vscroll.set, xscrollcommand=self.Hscroll.set) # XY scroll area for table data
self.Vscroll.config(command = self.table_scroll_Y) #configures command for Y on both scroll areas
self.Hscroll.config(command = self.table_data.xview) #configure command for X on data scroll region
#crate frames to hold all the widgets
title_frame = Frame(self.table_title, bg="orange")
title_frame.pack(padx=15, pady=15, fill=BOTH, expand=1)
data_frame = Frame(self.table_data, bg="purple")
data_frame.pack(padx=15, pady=15, fill=BOTH, expand=1)

#create windows and pack widgets
self.table_title.pack(side=TOP, fill=X, padx=5, pady=5)
self.table_data.pack(side=TOP, fill=BOTH, expand=1, padx=5, pady=5)
self.table_title.create_window(0,0, window=title_frame)
self.table_data.create_window(0,0, window=data_frame)
self.table_title.config(scrollregion=self.table_title.bbox("all"))
self.table_data.config(scrollregion=self.table_data.bbox("all"))
self.table_title.yview_moveto(0) 
self.table_data.yview_moveto(0)
self.table_data.xview_moveto(0)
#Build table column headers
row = self.tku.cFrame(title_frame, fill=X, borderwidth=1, relief="ridge", highlightbackground="black")
for item in cols:
Label(row, text=item, width=len(item)+1, borderwidth=2, relief="groove", heigh=rheight, bg=colour1).pack(side=LEFT, fill=X, expand=1)
rowsize.append(len(item)+1)
#Build table data
i = 0
for datarow in data:
row = self.tku.cFrame(data_frame, fill=X, borderwidth=1, relief="ridge", highlightbackground="black")
for key, value in datarow.items():
Label(row, text=value, width=rowsize[i], borderwidth=2, relief="groove", heigh=rheight, bg="white").pack(side=LEFT, fill=X, expand=1)
if i <= len(rowsize):
i = 0
else:
i+=1

在我的代码中,滚动条在正确的位置,但小部件似乎向左偏移,偏离了它们内置的框架的顶部(self.tablebase是一个标准框架,用于容纳所有表格内容(。

所以我设法将滚动条重新绑定到它们各自的区域,用一个完整的lambda函数替换命令=canvas.xview,该函数将它绑定到两个cavas对象并将它们一起滚动。

def table_scroll_X(self, *args): # args = ('moveto', 0-1) and can be used with xview_moveto(pos) command
self.table_title.xview_moveto(args[1])
self.table_data.xview_moveto(args[1])
def build_table(self, cols, data):
# Clear existing widget so we have a fresh start (used for updating to a new table)
for child in self.tablebase.winfo_children(): 
child.pack_forget()
child.destroy()
##---
colour1 = "#EEEEEE" # sets title colour to a light gray colour
rheight = 1 # sets row height
rowsize = [] # used to keep row sizes uniform

#Note: self.tku.cFrame(**kwrds) ==  'frame = Frame(*args)' and 'frame.pack(*args)' with 'return frame', used to make crating common widgets a little quicker.

#split between table area and scroll bar for fixed Y scroll (Prevents scrolling the scrollbar off screen)
layout1=self.tku.cFrame(self.tablebase, side=LEFT,  fill=BOTH, expand=1, bg="white") 
self.Vscroll = Scrollbar(self.tablebase, orient="vertical")
self.Vscroll.pack(side=RIGHT, fill=Y)
#split between table area and scroll bar for fixed X scroll
layout2 = self.tku.cFrame(layout1, side=TOP, fill=BOTH, expand=1, bg="white")
self.Hscroll = Scrollbar(layout1, orient="horizontal")
self.Hscroll.pack(side=BOTTOM, fill=X)

#create the Canvas objects that can be scrolled
self.table_title = Canvas(layout2, bg="white", highlightthickness=0, height=25) #X scroll area for Column titles
self.table_data = Canvas(layout2, bg="white", highlightthickness=0, yscrollcommand=self.Vscroll.set, xscrollcommand=self.Hscroll.set) # X/Y scroll area for table data
self.Vscroll.config(command = self.table_data.yview) #configures command for Y only on the data (up/down)
self.Hscroll.config(command = self.table_scroll_X) #configure command for X on data scroll region (left/right)

#crate frames to hold all the widgets
title_frame = Frame(self.table_title, bg="white")
title_frame.pack(padx=15, pady=15, fill=BOTH, expand=1)
data_frame = Frame(self.table_data, bg="white")
data_frame.pack(padx=15, pady=15, fill=BOTH, expand=1)

#create windows and pack widgets
self.table_title.pack(side=TOP, fill=X, padx=0, pady=0)
self.table_data.pack(side=TOP, fill=BOTH, expand=1, padx=0, pady=0)
title_frame.bind("<Configure>",lambda e: self.table_title.configure(scrollregion=self.table_title.bbox("all")))
data_frame.bind("<Configure>",lambda e: self.table_data.configure(scrollregion=self.table_data.bbox("all")))
self.table_title.create_window(0,0, window=title_frame)
self.table_data.create_window(0,0, window=data_frame)
#Build table column headers
row = self.tku.cFrame(title_frame, fill=X, borderwidth=1, relief="ridge", highlightbackground="black", side=LEFT)
i = 0
for item in cols:
rowsize.append(math.ceil(len(item)*1.7)) # allows for some text size discrepencys.
Label(row, text=item, font='TkFixedFont', width=rowsize[i], borderwidth=2, relief="groove", heigh=rheight, bg=colour1).pack(side=LEFT)
if i <= len(rowsize):
i=0
else:
i+=1
#Build table data
print(rowsize)
i = 0
for datarow in data:
row = self.tku.cFrame(data_frame, fill=X, borderwidth=1, relief="ridge", highlightbackground="black")
for key, value in datarow.items():
Label(row, text=value, font='TkFixedFont', width=rowsize[i], borderwidth=2, relief="groove", heigh=rheight, bg="white").pack(side=LEFT)
if i <= len(rowsize):
i=0
else:
i+=1
#update the interface to apply sizing and move all scrollbars to 0,0
self.root.update()
self.root.update_idletasks()
self.table_title.yview_moveto(0) 
self.table_data.yview_moveto(0)
self.table_title.xview_moveto(0)
self.table_data.xview_moveto(0)

如果您只想冻结一行或一列,或者同时冻结这两行或这两列,可以将其重新实现为让滚动条控制多个画布对象。

最新更新