首页 > 解决方案 > 如何防止 tkinter 画布的子窗口跨过画布滚动条

问题描述

我正在构建一个带有多个小部件的画布。滚动条工作正常,但他们踩到了看起来不太好的滚动条。是否可以在不踩滚动条的情况下使子窗口包含在画布中?我尝试在画布中添加一个框架并将我的小部件添加到该框架,但它遇到了其他一些问题。

子窗口越界滚动条

from tkinter import *
from tkinter import ttk
from tkinter import messagebox

class MainUI:
    def __init__(self,master):
        self.master = master
        self.content = ttk.Frame(self.master, padding=(3,3,12,12))

        #row 4
        self.canvasFrame = ttk.Frame(self.content,borderwidth=5, relief="sunken")


        self.canvasFrame.grid(row=0, column=0, columnspan=3, sticky=W+E+N+S, pady=5, padx=15)


        self.xscrollbar = Scrollbar(self.canvasFrame, orient=HORIZONTAL)
        self.xscrollbar.grid(row=1, column=0, sticky=E+W)

        self.yscrollbar = Scrollbar(self.canvasFrame)
        self.yscrollbar.grid(row=0, column=1, sticky=N+S)

        self.canvas = Canvas(self.canvasFrame, bd=0, 
#                         scrollregion=(0, 0, 1000, 1000),
                        xscrollcommand=self.xscrollbar.set,
                        yscrollcommand=self.yscrollbar.set)

        self.xscrollbar.config(command=self.canvas.xview)
        self.yscrollbar.config(command=self.canvas.yview)

        #listbox
        self.listFrame = ttk.Frame(self.content,borderwidth=5, relief="sunken")

        self.listFrame.grid(row=0, column=3, columnspan=2, sticky=W+E+N+S, pady=5, padx=15)

        listYscrollbar = Scrollbar(self.listFrame)
        listYscrollbar.grid(row=0, column=1, sticky=N+S)
        self.actualCostlistbox = Listbox(self.listFrame)
        self.actualCostlistbox.grid(row=0, column=0, sticky=W+E+N+S)
        self.actualCostlistbox.config(yscrollcommand=listYscrollbar.set)
        listYscrollbar.config(command=self.actualCostlistbox.yview)


        self.canvas.grid(row=0, column=0, sticky=N+S+E+W)

        self.content.grid(column=0, row=0, sticky=(N, S, E, W))

        self.master.grid_rowconfigure(0,weight=1)
        self.master.grid_columnconfigure(0,weight=1)

        self.content.grid_rowconfigure(0,weight=1)
        self.content.grid_columnconfigure(0,weight=1)
        self.content.grid_columnconfigure(1,weight=1)
        self.content.grid_columnconfigure(2,weight=1)
        self.content.grid_columnconfigure(3,weight=1)

        self.canvasFrame.grid_rowconfigure(0,weight=1)
        self.canvasFrame.grid_columnconfigure(0,weight=1)

        self.listFrame.grid_rowconfigure(0,weight=1)
        self.listFrame.grid_columnconfigure(0,weight=1)

        self.addEmpColumn()
        self.canvas.configure(scrollregion = self.canvas.bbox("all"))

        #events binding
        self.canvas.bind("<Enter>", self.bound_to_mousewheel)
        self.canvas.bind("<Leave>", self.unbound_to_mousewheel)

    def addEmpColumn(self):
        self.empComboBoxList = []
        self.empList=['a','b','c']
        for i in range(1, 30):
            empCombo =   ttk.Combobox(self.canvasFrame, 
                                                  values=self.empList)
            self.empComboBoxList.append(empCombo)
            self.canvas.create_window(5, i * 25, anchor=NW, window=empCombo)

    def mouse_wheel(self, event):
        if self.yscrollbar.get() != (0.0, 1.0):
            self.canvas.yview_scroll(-1 * int(event.delta / 60), "units")
        if self.xscrollbar.get() != (0.0, 1.0):
            self.canvas.xview_scroll(-1 * int(event.delta / 60), "units")

    def bound_to_mousewheel(self, event):
        self.canvas.bind_all("<MouseWheel>", self.mouse_wheel)

    def unbound_to_mousewheel(self, event):
        self.canvas.unbind_all("<MouseWheel>")

def on_closing():
    root.destroy()



root = Tk()   
mainui = MainUI(root)
root.title("Test")
root.protocol("WM_DELETE_WINDOW", on_closing)
root.mainloop()

标签: pythoncanvastkinterscrollbar

解决方案


我相信问题出在:

def addEmpColumn(self):
    self.empComboBoxList = []
    self.empList=['a','b','c']
    for i in range(1, 30):
        empCombo =   ttk.Combobox(self.canvasFrame, 
                                              values=self.empList)
        self.empComboBoxList.append(empCombo)
        self.canvas.create_window(5, i * 25, anchor=NW, window=empCombo)

在行中:

empCombo = ttk.Combobox(self.canvasFrame, values=self.empList)

它将 放置Combobox在画布的框架中,而不是画布中。

empCombo = ttk.Combobox(self.canvas, values=self.empList)

在此处输入图像描述


推荐阅读