python - 水平和垂直滚动的问题
问题描述
我正在编写一个简单的电子表格查看器。我想要的是第 0 行是控件而不是滚动,第 1 行是列标题并与数据一起水平滚动,第 2 行到第 -1 行是数据并且水平和垂直滚动以及远处的滚动条右,最后一行是水平滚动条。我希望程序填满整个窗口。我现在只使用了窗口的左上角四分之一,水平滚动有效,但没有数据,也没有垂直滚动条。
import tkinter as tk
from tkinter import messagebox
def NewFrame(parent,d,ro = 0, co = 0, st = "NEWS", w = 1):
fr = tk.Frame(parent, **d)
fr.grid(row=ro,column=co, sticky=st)
fr.grid_columnconfigure(co, weight=w)
fr.grid_rowconfigure(ro, weight=w)
return fr
def NewCanvas(parent,d,ro = 0, co = 0, st = "NEWS", w = 1):
ca = tk.Canvas(parent, **d)
ca.grid(row=ro,column=co, sticky=st)
ca.grid_columnconfigure(co, weight=w)
ca.grid_rowconfigure(ro, weight=w)
return ca
class test:
def __init__(self,root,hxw):
self.hxw=hxw
root.wm_title("Test")
root.configure(bd=2)
root.configure(background="black")
root.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(0, weight=1)
root.grid_rowconfigure(1, weight=1)
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
if not self.hxw:
self.hxw='{0:d}x{1:d}+{2:d}+{3:d}'.format(min(940,screen_width),min(560,screen_height),int(screen_width/3),int(screen_height/3))
root.geometry(self.hxw) #Width x Height
root.update()
self.top = root
self.topFrame = NewFrame(self.top, {'height':25, 'background':"blue"}, st="NEW")
tk.Button(self.topFrame, text="Help", command=self.callback4).grid(row=0, column=0, sticky='E')
self.hsFrame = NewFrame(self.top, {'background':"red"}, st="NEW", ro=1)
self.hcanvas = NewCanvas(self.hsFrame, {'background':"green"}, st="NEW")
self.mFrame = NewFrame(self.hcanvas,{})
self.mFrame.bind(
"<Configure>",
lambda e: self.hcanvas.configure(
scrollregion=self.hcanvas.bbox("all")
)
)
self.hcanvas.create_window((0, 0), window=self.mFrame, anchor="nw")
# Create a horizontal scrollbar linked to the canvas.
hsbar = tk.Scrollbar(self.hsFrame, orient=tk.HORIZONTAL, command=self.hcanvas.xview)
hsbar.grid(row=2, column=0, sticky=tk.EW)
self.hcanvas.configure(xscrollcommand=hsbar.set)
self.labelFrame = NewFrame(self.mFrame, {'background':"grey", 'height':25}) #place a frame on the canvas, this frame will hold the child widgets
for col in range(20):
tkl = tk.Label(self.labelFrame, width=20, borderwidth="1", relief="solid", text=("col %d" % (col+1)))
tkl.grid(row=0, column=col, sticky='news')
self.labelFrame.grid_columnconfigure(col,weight=1)
self.vsFrame = NewFrame(self.mFrame, {'background':"yellow"})
self.vcanvas = NewCanvas(self.vsFrame, {'background':"#ff00ff"})
self.botFrame = NewFrame(self.vcanvas, {'background':"orange"}) #place a frame on the canvas, this frame will hold the child widgets
self.botFrame.bind(
"<Configure>",
lambda e: self.vcanvas.configure(
scrollregion=self.vcanvas.bbox("all")
)
)
self.vcanvas.create_window((0, 0), window=self.vsFrame, anchor="nw")
## # Create a vertical scrollbar linked to the canvas.
self.vsbar = tk.Scrollbar(self.vsFrame, orient=tk.VERTICAL, command=self.vcanvas.yview)
self.vsbar.grid(row=0, column=1, sticky=tk.NS)
self.vcanvas.configure(yscrollcommand=self.vsbar.set)
#
# Add 50-by-20 labels to the frame
rows = 50
columns = 20
for i in range(0, rows):
for j in range(0, columns):
tkl = tk.Label(self.botFrame, width=10, borderwidth="1", relief="solid", text=("%d,%d" % (i+1, j+1)))
tkl.grid(row=i, column=j, sticky='news')
self.botFrame.grid_columnconfigure(j, weight=1)
def callback4(self):
print('root', root.winfo_geometry())
print('self.topFrame', self.topFrame.winfo_geometry())
print('self.hsFrame', self.hsFrame.winfo_geometry())
print('self.hcanvas', self.hcanvas.winfo_geometry())
print('self.mFrame', self.mFrame.winfo_geometry())
print('self.labelFrame', self.labelFrame.winfo_geometry())
print('self.vsFrame', self.vsFrame.winfo_geometry())
print('self.vcanvas', self.vcanvas.winfo_geometry())
print('self.botFrame', self.botFrame.winfo_geometry())
print('------------------------------')
messagebox.showinfo(
"help",
"This is help"
)
# Launch the GUI
root = tk.Tk()
test(root,None)
root.mainloop()
解决方案
import tkinter as tk
from tkinter import messagebox
def flexx(o, r = 0, c = 0, rw = 1, cw = 1):
"""flexx is used on other widgets (Text, Canvas, Listbox, Button etc)"""
if r != None:
o.grid_rowconfigure(r, weight = rw)
if c != None:
o.grid_columnconfigure(c, weight = cw)
class test:
def callback( self ):
pass
def screencenter( self, o ):
w, h = o.winfo_width( ), o.winfo_height( )
x, y = o.winfo_screenwidth( ) - w, o.winfo_screenheight( ) - h
o.geometry( f'{w}x{h}+{int(x/2)}+{int(y/2)}' )
def closer(self, ev):
self.master.destroy()
def __init__(self, hxw):
self.master = tk.Tk()
self.master.withdraw()
self.hxw = hxw
self.master.wm_title("Test")
self.master.configure(bd = 2)
for r in range(4):
flexx(self.master, r = r)
self.master.bind("<Escape>", self.closer)
sw = self.master.winfo_screenwidth()
sh = self.master.winfo_screenheight()
if not self.hxw:
self.hxw = f"{min(940,sw)}x{min(660,sh)}"
# First section 7 lines
self.topFrame = tk.Frame(
self.master, height = 25, bg = "blue")
self.topFrame.grid(row = 0,column = 0, sticky = "new")
flexx(self.topFrame)
self.helper = tk.Button(
self.topFrame, text = "Help", command = self.callback)
self.helper.grid(row = 0, column = 0, sticky = "e")
# Second section 29
self.hsFrame = tk.Frame(self.master, bg = "red")
self.hsFrame.grid(row = 1, column = 0, sticky = "nsew")
flexx(self.hsFrame, r = 1)
self.hcanvas = tk.Canvas(self.hsFrame, bg = "green")
self.hcanvas.grid(row = 0, column = 0, sticky = "nsew")
self.mFrame = tk.Frame(self.hsFrame, bg = "cyan")
self.mFrame.grid(row = 1, column = 0, sticky = "new")
flexx(self.mFrame, r = 0)
self.mFrame.bind(
"<Configure>",
lambda e: self.hcanvas.configure(
scrollregion = self.hcanvas.bbox("all") ))
item = self.hcanvas.create_window( (400,20), window = self.mFrame)
self.labelFrame = tk.LabelFrame(self.mFrame, bg = "magenta")
self.labelFrame.grid(row = 0,column = 0, sticky = "new")
for col in range(20):
tkl = tk.Label(
self.labelFrame, width = 10, bd = 1,
relief = "solid", text = f"col {col+1}")
tkl.grid(row = 0, column = col, sticky = "nsew")
hsbar = tk.Scrollbar(
self.hsFrame, orient = "horizontal", command = self.hcanvas.xview)
hsbar.grid(row = 2, column = 0, sticky = "ew")
self.hcanvas.configure(xscrollcommand = hsbar.set)
# Third section 38 lines
self.HsFrame = tk.Frame(self.master, bg = "red")
self.HsFrame.grid(row = 4, column = 0, sticky = "nsew")
flexx(self.HsFrame, r = 4)
self.Hcanvas = tk.Canvas(self.HsFrame, bg = "green")
self.Hcanvas.grid(row = 0, column = 0, sticky = "nsew")
self.MFrame = tk.Frame(self.HsFrame, bg = "cyan")
self.MFrame.grid(row = 1, column = 0, sticky = "new")
flexx(self.MFrame, r = 0)
self.MFrame.bind(
"<Configure>",
lambda e: self.Hcanvas.configure(
scrollregion = self.Hcanvas.bbox("all") ))
item1 = self.Hcanvas.create_window( (400,20), window = self.MFrame)
self.LabelFrame = tk.LabelFrame(self.MFrame, bg = "magenta")
self.LabelFrame.grid(row = 0,column = 0, sticky = "new")
rows = columns = 20
for i in range(rows):
for j in range(columns):
tkl = tk.Label(
self.LabelFrame, width = 10, borderwidth = 1,
relief = "solid", text = f"{i+1},{j+1}")
tkl.grid(row = i, column = j, sticky = "nsew")
flexx(self.LabelFrame, r = i, c = j)
Hsbar = tk.Scrollbar(
self.HsFrame, orient = "horizontal", command = self.Hcanvas.xview)
Hsbar.grid(row = 2, column = 0, sticky = "ew")
self.Hcanvas.configure(xscrollcommand = Hsbar.set)
Vsbar = tk.Scrollbar(
self.HsFrame, orient = "vertical", command = self.Hcanvas.yview)
Vsbar.grid(row = 0, column = 1, sticky = "ns")
self.Hcanvas.configure(yscrollcommand = Vsbar.set)
# set size and center it
self.master.geometry(self.hxw) # Width x Height
self.master.update()
self.screencenter( self.master )
self.master.deiconify()
if __name__ == "__main__":
SpreadSheet = test(None)
SpreadSheet.master.mainloop()
推荐阅读
- node.js - 使用 genType 导出具有超过 1 个参数的 rescript 函数时出现 Curry.js 错误
- javascript - 使用 Instagram API 从 Javascript 将图像发布到 Instagram
- reactjs - 使用 Mongoose 的 find() 时遇到问题,正确的使用方法是什么?
- firebase - 如何从所有文档的子集合中检索所有数据
- angular - Angular + firebase:从服务文件调用函数时.then()不起作用
- python - 如何修复 ValueError:要解包的值太多(预期为 2)?
- python - 更新多维 Numpy 数组 Python
- next.js - 在 next.js 中添加带有 css 变量的内联样式
- amazon-web-services - Lambda 调用 Lambda 导致 InvalidSignatureException
- python - flask-sqlalchemy 中有没有办法删除或创建单个表?