tkinter 带滚动条的框架 - 元素溢出到其他框架

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

我想制作一个带有两个垂直堆叠框架的用户界面:

  • frame1
    :输入设置
  • frame2
    :绘图

我需要很多参数,需要滚动条。我尝试了不同的类,用框架实现滚动条,但它们似乎都有相同的问题。

问题是,虽然我有一个可以工作的滚动条,但它不会隐藏画布所附加的框架可见区域之外的元素。这意味着它们溢出到其他框架:

picture

所以你可以看到顶部框架之外的元素仍然以某种方式显示 - 继续第二个。

理解下面问题的代码。 有什么建议吗?

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 的位置。另外,我的程序中的顶框实际上是一个笔记本,但这并不能改变溢出问题。

python tkinter tkinter-canvas
1个回答
0
投票

问题在于 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 使用的语法。

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