我想制作一个带有两个垂直堆叠框架的用户界面:
frame1
:输入设置frame2
:绘图我需要很多参数,需要滚动条。我尝试了不同的类,用框架实现滚动条,但它们似乎都有相同的问题。
问题是,虽然我有一个可以工作的滚动条,但它不会隐藏画布所附加的框架可见区域之外的元素。这意味着它们溢出到其他框架:
所以你可以看到顶部框架之外的元素仍然以某种方式显示 - 继续第二个。
理解下面问题的代码。 有什么建议吗?
import tkinter as tk
from tkinter import ttk
from tkinter.constants import *
class VerticalScrolledFrame(ttk.Frame):
def __init__(self, *args, **kw):
ttk.Frame.__init__(self, *args, **kw)
# Create a canvas object and a vertical scrollbar for scrolling it.
vscrollbar = ttk.Scrollbar(self, orient=VERTICAL)
vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)
self.canvas = tk.Canvas(self, bd=0, highlightthickness=0, yscrollcommand=vscrollbar.set)
self.canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
vscrollbar.config(command = self.canvas.yview)
# Reset the view
self.canvas.xview_moveto(0)
self.canvas.yview_moveto(0)
# Create a frame inside the canvas which will be scrolled with it.
self.interior = ttk.Frame(self.canvas)
self.interior.bind('<Configure>', self._configure_interior)
self.canvas.bind('<Configure>', self._configure_canvas)
self.interior_id = self.canvas.create_window(0, 0, window=self.interior, anchor=NW)
def _configure_interior(self, event):
# Update the scrollbars to match the size of the inner frame.
size = (self.interior.winfo_reqwidth(), self.interior.winfo_reqheight())
self.canvas.config(scrollregion=(0, 0, size[0], size[1]))
if self.interior.winfo_reqwidth() != self.canvas.winfo_width():
# Update the canvas's width to fit the inner frame.
self.canvas.config(width = self.interior.winfo_reqwidth())
def _configure_canvas(self, event):
if self.interior.winfo_reqwidth() != self.canvas.winfo_width():
# Update the inner frame's width to fill the canvas.
self.canvas.itemconfigure(self.interior_id, width=self.canvas.winfo_width())
#Create 2 vertically stacked frames and add it to the root
root = tk.Tk()
root.geometry('1280x1024')
root.resizable(width=True,height=True)
topframe = ttk.LabelFrame(root,text='Top', width=1280, height=200)
mainframe = ttk.LabelFrame(root,text='Results', width=1280, height=1024-200)
topframe.grid(row=0,column=0,sticky='news')
mainframe.grid(row=1,column=0,sticky='news')
#Create scrolled frame
frame = VerticalScrolledFrame()
#Add many elements to it, that would require a scrollbar
for i in range(20):
ttk.Label(text=f'Entry {i}').grid(in_=frame.interior,row=i,column=0,sticky='news')
#Resizing the frames
frame.grid(in_=topframe,row=0,column=0,sticky='news')
topframe.columnconfigure(0,weight=1)
topframe.rowconfigure(0,weight=1)
root.mainloop()
我尝试了很多,但没有任何效果。最初,我使用 relwidth/relheight 设置 topframe/mainframe 的位置。另外,我的程序中的顶框实际上是一个笔记本,但这并不能改变溢出问题。
问题在于 tkinter 使用父/子关系来确定堆叠顺序(即:哪些小部件在 Z 轴上出现在其他小部件的顶部)。由于您将标签创建为根窗口的子窗口,因此它们的堆叠顺序将高于另一个框架内画布内的框架。
最简单的解决方案是使标签成为内框架的子级,或者继续使用
in_
并使标签成为 frame
(VerticalScrolledFrame
的实例)的子级
for i in range(20):
ttk.Label(frame, text=f'Entry{i}').grid(in_=frame.interior,...)
有关堆叠顺序的详细讨论,请参阅 Tcler wiki 上的 Stacking Order。这些示例都是 tcl 语言而不是 python 语言,但是很容易在心里翻译成 tkinter 使用的语法。