Tkinter:全功能滚动框,自动隐藏滚动条,除了bord

2024-04-23 21:02:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我在tkinter(class ScrolledWindow)中将发现的许多部分代码组合在一起,以实现功能全面的滚动Frame。很好用。在

使用鼠标滚轮滚动时仍然存在一个小问题(当没有滚动条时)。我以为是边界问题或类似的问题,但找不到问题或解决办法(这对tkinter来说很新鲜)。如果您能帮助您完善这个tkinter滚动框,我们将不胜感激。在

代码示例:

# -*- coding: utf8 -*-
'''
Created on 16 juin 2016

@author: Chevalier Thierry
'''
import tkinter, tkinter.scrolledtext
import tkinter.ttk

class ScrolledWindow(tkinter.ttk.Frame):
    """
    Parent = master of scrolled window
    """
    def __init__(self, parent, *args, **kwargs):
        """Parent = master of scrolled window
       """
        super().__init__(parent, *args, **kwargs)
        self.parent = parent
        # creating a scrollbars and canvas
        self.xScrollbar = tkinter.ttk.Scrollbar(self, orient = 'horizontal')
        self.yScrollbar = tkinter.ttk.Scrollbar(self)
        self.scrollCanvas = tkinter.Canvas(self)
        ##self.scrollCanvas.config(relief = 'flat', width = 100, heigh = 100, bd = 0)
        self.scrollCanvas.config(relief = 'flat', bd = 0)
        # placing scrollbar and  canvas into frame
        self.xScrollbar.grid(column = 0, row = 1, sticky="NESW", columnspan = 2)
        self.yScrollbar.grid(column = 1, row = 0, sticky="NESW")
        self.scrollCanvas.grid(column = 0, row = 0, columnspan=1,rowspan=1,sticky="NESW",padx=0,pady=0,ipadx=0,ipady=0)
        self.grid_columnconfigure(0,weight=1)
        self.grid_columnconfigure(1,weight=0)
        self.grid_rowconfigure(0,weight=1)
        self.grid_rowconfigure(1,weight=0)
        # accociating scrollbar comands to canvas scroling
        self.xScrollbar.config(command = self.scrollCanvas.xview)
        self.yScrollbar.config(command = self.scrollCanvas.yview)
        self.scrollCanvas.config(xscrollcommand = self.xScrollbar.set, yscrollcommand = self.yScrollbar.set)
        # creating a frame to inserto to canvas
        self.scrollWindow = tkinter.ttk.Frame(self.scrollCanvas)
        self.scrollWindowItemId = self.scrollCanvas.create_window(0, 0, window = self.scrollWindow, anchor = 'nw')

        self.scrollWindow.bind('<Configure>', self._configure_scrollWindow)
        self.scrollCanvas.bind('<Configure>', self._configure_scrollCanvas)
        self.scrollWindow.bind('<Enter>', self._bound_to_mousewheel)
        self.scrollWindow.bind('<Leave>', self._unbound_to_mousewheel)

    def _bound_to_mousewheel(self, event):
        self.scrollCanvas.bind_all("<MouseWheel>", self._on_mousewheel)
    def _unbound_to_mousewheel(self, event):
        self.scrollCanvas.unbind_all("<MouseWheel>")
    def _on_mousewheel(self, event):
        self.scrollCanvas.yview_scroll(int(-1*(event.delta/120)), "units")

    def _configure_scrollWindow(self, event):
        print("_configure_scrollWindow:")
        print("    scrollWindow", "w=", event.width, "h", event.height)
        size = (self.scrollWindow.winfo_reqwidth(), self.scrollWindow.winfo_reqheight())
        print("    scrollWindow reqwidth and reqheight", "w=", size[0], ", h=", size[1])
        print("    scrollCanvas", "w=", self.scrollCanvas.winfo_width(), ", h=", self.scrollCanvas.winfo_height())

    def _configure_scrollCanvas(self, event):
        print("_configure_scrollCanvas:")
        print("    scrollCanvas", "w=", event.width, self.scrollCanvas.winfo_width(), ", h=", event.height, self.scrollCanvas.winfo_height())
        #=======================================================================
        # if self.scrollWindow.winfo_reqwidth() != self.scrollCanvas.winfo_width():
        #     # update the inner frame's width to fill the canvas
        #     self.scrollCanvas.itemconfig(self.scrollWindowItemId, width=self.scrollCanvas.winfo_width())
        # if self.scrollWindow.winfo_reqheight() != self.scrollCanvas.winfo_height():
        #     # update the inner frame's width to fill the canvas
        #     self.scrollCanvas.itemconfig(self.scrollWindowItemId, height=self.scrollCanvas.winfo_height())
        #=======================================================================
        canvasWidth, canvasHeight = (self.scrollCanvas.winfo_width(), self.scrollCanvas.winfo_height())
        canvasWidth, canvasHeight = (event.width, event.height)
        windowReqWidth, windowReqHeight = (self.scrollWindow.winfo_reqwidth(), self.scrollWindow.winfo_reqheight())
        if windowReqWidth < canvasWidth:
            if windowReqHeight < canvasHeight:
                # windowReqWidth < canvasWidth and windowReqHeight < canvasHeight
                self.scrollCanvas.itemconfig(self.scrollWindowItemId, width=canvasWidth, height=canvasHeight)
                ##self.scrollCanvas.config(scrollregion='0 0 %s %s' % (canvasWidth, canvasHeight))
                self.scrollCanvas.config(scrollregion=self.scrollCanvas.bbox("all"))
                self.tk.call("grid", "remove", self.xScrollbar)
                self.tk.call("grid", "remove", self.yScrollbar)
            else:
                # windowReqWidth < canvasWidth and windowReqHeight > canvasHeight
                self.scrollCanvas.config(width = canvasWidth, height = windowReqHeight)
                self.scrollCanvas.itemconfig(self.scrollWindowItemId, width=canvasWidth, height=windowReqHeight)
                ##self.scrollCanvas.config(scrollregion='0 0 %s %s' % (canvasWidth, windowReqHeight))
                self.scrollCanvas.config(scrollregion=self.scrollCanvas.bbox("all"))
                self.tk.call("grid", "remove", self.xScrollbar)
                self.yScrollbar.grid()
        else: # windowReqWidth >  canvasWidth
            if windowReqHeight < canvasHeight:
                # windowReqWidth > canvasWidth and windowReqHeight < canvasHeight
                self.scrollCanvas.config(width = windowReqWidth, height = canvasHeight)
                self.scrollCanvas.itemconfig(self.scrollWindowItemId, width=windowReqWidth, height=canvasHeight)
                ##self.scrollCanvas.config(scrollregion='0 0 %s %s' % (windowReqWidth, canvasHeight))
                self.scrollCanvas.config(scrollregion=self.scrollCanvas.bbox("all"))
                self.xScrollbar.grid()
                self.tk.call("grid", "remove", self.yScrollbar)
            else:
                # windowReqWidth > canvasWidth and windowReqHeight > canvasHeight
                self.scrollCanvas.config(width = windowReqWidth, height = windowReqHeight)
                self.scrollCanvas.itemconfig(self.scrollWindowItemId, width=windowReqWidth, height=windowReqHeight)
                ##self.scrollCanvas.config(scrollregion='0 0 %s %s' % (windowReqWidth, windowReqHeight))
                self.scrollCanvas.config(scrollregion=self.scrollCanvas.bbox("all"))
                self.xScrollbar.grid()
                self.yScrollbar.grid()

    def getScrollWindow(self):
        return self.scrollWindow

class tkTestingGUI(tkinter.ttk.Frame):
    def __init__(self, master):
        super().__init__(master)
        self.initialize()
        self.pack(fill="both", expand=1)
        self.master.resizable(True,True)

    def initialize(self):
               #
        # main frame definition
        #
        leftFrame=tkinter.ttk.Frame(self, borderwidth=0)
        rightFrame=tkinter.ttk.Frame(self, borderwidth=0)
        leftFrame.grid(column=0,row=0,columnspan=1,rowspan=1,sticky=tkinter.N+tkinter.S+tkinter.E+tkinter.W,padx=1,pady=1,ipadx=0,ipady=0)
        rightFrame.grid(column=1,row=0,columnspan=1,rowspan=1,sticky='NESW',padx=1,pady=1,ipadx=0,ipady=0)
        self.grid_columnconfigure(0,weight=1)
        self.grid_columnconfigure(1,weight=1)
        self.grid_rowconfigure(0,weight=1)

        scrolledLeftFrame = ScrolledWindow(self, borderwidth=0)
        rightFrame=tkinter.ttk.Frame(self, borderwidth=0)
        scrolledLeftFrame.grid(column=0,row=0,columnspan=1,rowspan=1,sticky=tkinter.N+tkinter.S+tkinter.E+tkinter.W,padx=1,pady=1,ipadx=0,ipady=0)
        rightFrame.grid(column=1,row=0,columnspan=1,rowspan=1,sticky="NESW",padx=1,pady=1,ipadx=0,ipady=0)
        self.grid_columnconfigure(0,weight=1)
        self.grid_columnconfigure(1,weight=1)
        self.grid_rowconfigure(0,weight=1)

        # get real inside left frame
        leftFrame = scrolledLeftFrame.getScrollWindow() # real inside window to put widgets

        #
        # left frame definition
        #
        self.idFrame = tkinter.ttk.Frame(leftFrame, borderwidth=0)
        ##self.idFrame.grid(column=0,row=0,columnspan=1,rowspan=1,sticky='NESW', padx=1,pady=1,ipadx=0,ipady=0)
        self.idFrame.grid(column=0,row=0,sticky='NESW')
        label = tkinter.ttk.Label(self.idFrame, text="Test").grid(column=0, row=0, sticky="NESW")
        label = tkinter.ttk.Label(self.idFrame, text="Test").grid(column=1, row=0, sticky="NESW")
        label = tkinter.ttk.Label(self.idFrame, text="Test").grid(column=2, row=0, sticky="NESW")

        label = tkinter.ttk.Label(self.idFrame, text="Test").grid(column=0, row=1, sticky="NESW")
        label = tkinter.ttk.Label(self.idFrame, text="Test").grid(column=1, row=1, sticky="NESW")
        label = tkinter.ttk.Label(self.idFrame, text="Test").grid(column=2, row=1, sticky="NESW")
        label = tkinter.ttk.Label(self.idFrame, text="Test", anchor="e").grid(column=3, row=1, sticky=tkinter.E)
        entry2 = tkinter.ttk.Entry(self.idFrame,text="A")
        entry2.grid(column=4,row=0,columnspan=1,rowspan=1,sticky='EW',padx=1,pady=1,ipadx=0,ipady=0)
        self.idFrame.grid_columnconfigure(0,weight=1)
        label = tkinter.ttk.Label(self.idFrame, text="Test").grid(column=0, row=2, sticky="NESW")
        label = tkinter.ttk.Label(self.idFrame, text="Test").grid(column=1, row=2, sticky="NESW")
        label = tkinter.ttk.Label(self.idFrame, text="Test").grid(column=2, row=2, sticky="NESW")
        label = tkinter.ttk.Label(self.idFrame, text="Test").grid(column=0, row=3, sticky="NESW")
        label = tkinter.ttk.Label(self.idFrame, text="Test").grid(column=1, row=3, sticky="NESW")
        label = tkinter.ttk.Label(self.idFrame, text="Test").grid(column=2, row=3, sticky="NESW")

        #
        self.activeEventsFrame = tkinter.ttk.Frame(leftFrame, borderwidth=0)
        self.activeEventsFrame.grid(column=0,row=1,columnspan=1,rowspan=1,sticky='NESW',padx=1,pady=1,ipadx=0,ipady=0)
        label = tkinter.ttk.Label(self.activeEventsFrame, text="Test").grid(column=0, row=0, sticky="NESW")
        label = tkinter.ttk.Label(self.activeEventsFrame, text="Test").grid(column=1, row=0, sticky="NESW")
        label = tkinter.ttk.Label(self.activeEventsFrame, text="Test long").grid(column=2, row=0, sticky="NESW")


        #
        leftFrame.grid_columnconfigure(0,weight=1)
        leftFrame.grid_rowconfigure(0,weight=1)
        leftFrame.grid_rowconfigure(1,weight=1)

        #
        # right frame definition
        #
        self.inputText = tkinter.scrolledtext.ScrolledText(rightFrame)
        self.inputText.insert(tkinter.END, "Paste your text here.....")
        self.inputText.grid(column=0,row=0,columnspan=1,rowspan=1,sticky="NESW",padx=1,pady=1,ipadx=0,ipady=0)
        #
        rightFrame.grid_columnconfigure(0,weight=1)
        rightFrame.grid_rowconfigure(0,weight=1)

        #
        # update main frame
        #
        self.update()

    def quit(self):
        pass

if __name__ == "__main__":
    tkinterTk = tkinter.Tk()
    app = tkTestingGUI(master=tkinterTk)
    app.master.title('Testing TK')
    app.mainloop()

Tags: textselfconfigtkintercolumnwidthgridrow
1条回答
网友
1楼 · 发布于 2024-04-23 21:02:52

我找到了解决方案,最后,只需要将highlightthickness=0选项添加到canvas,因为默认值不为null。在

在下面找到功能齐全的滚动框,带有自动隐藏的滚动条和鼠标滚轮滚动(为更好的行为添加了一些修改)

# -*- coding: utf8 -*-
'''
Created on 16 juin 2016

@author: Chevalier Thierry
'''
import tkinter
import tkinter.ttk

class ScrolledWindow(tkinter.ttk.Frame):
    """

    Parent = master of scrolled window

    """

    def __init__(self, parent, *args, **kwargs):
        """Parent = master of scrolled window
       """
        super().__init__(parent, *args, **kwargs)
        self.parent = parent
        # creating scrollbars and canvas and window to contain future widgets of the scrolling area
        self.xScrollbar = tkinter.ttk.Scrollbar(self, orient = 'horizontal')
        self.yScrollbar = tkinter.ttk.Scrollbar(self)
        self.scrollCanvas = tkinter.Canvas(self)
        self.scrollCanvas.config(relief = 'flat', borderwidth=0, highlightthickness=0)
        self.scrollWindow = tkinter.ttk.Frame(self.scrollCanvas, borderwidth=0)
        # placing scrollbar and  canvas into frame and the scrollFrame into canvas
        self.xScrollbar.grid(column = 0, row = 1, sticky="NESW", columnspan = 2) 
        self.yScrollbar.grid(column = 1, row = 0, sticky="NESW")     
        self.scrollCanvas.grid(column = 0, row = 0, columnspan=1,rowspan=1,sticky="NESW",padx=0,pady=0,ipadx=0,ipady=0)
        self.scrollWindowItemId = self.scrollCanvas.create_window(0, 0, window = self.scrollWindow, anchor = 'nw')
        self.grid_columnconfigure(0,weight=1)
        self.grid_columnconfigure(1,weight=0)
        self.grid_rowconfigure(0,weight=1)
        self.grid_rowconfigure(1,weight=0)
        # accociating scrollbar comands to canvas scroling
        self.xScrollbar.config(command = self.scrollCanvas.xview)
        self.yScrollbar.config(command = self.scrollCanvas.yview)
        self.scrollCanvas.config(xscrollcommand = self.xScrollbar.set, yscrollcommand = self.yScrollbar.set)
        ##self.yScrollbar.lift(self.scrollWindow) # put to first plan     
        ##self.xScrollbar.lift(self.scrollWindow)
        self.scrollCanvas.bind('<Configure>', self._configure_scrollCanvas)
        ##self.scrollWindow.bind('<Configure>', self._configure_scrollWindow)
        self.scrollWindow.bind('<Enter>', self._bound_to_mousewheel)
        self.scrollWindow.bind('<Leave>', self._unbound_to_mousewheel)

    def _bound_to_mousewheel(self, event):
        self.scrollCanvas.bind_all("<MouseWheel>", self._on_mousewheel)   
    def _unbound_to_mousewheel(self, event):
        self.scrollCanvas.unbind_all("<MouseWheel>") 
    def _on_mousewheel(self, event):
        self.scrollCanvas.yview_scroll(int(-1*(event.delta/120)), "units")  

    def _configure_scrollWindow(self, event):
        print("_configure_scrollWindow:")
        print("    event", "w=", event.width, "h", event.height)
        print("    scrollWindow", "w=", self.scrollWindow.winfo_width(), ", h=", self.scrollWindow.winfo_height())
        print("    scrollWindow reqwidth and reqheight", "w=", self.scrollWindow.winfo_reqwidth(), ", h=", self.scrollWindow.winfo_reqheight())
        print("    scrollCanvas", "w=", self.scrollCanvas.winfo_width(), ", h=", self.scrollCanvas.winfo_height())
    def _configure_scrollCanvas(self, event):
        #=======================================================================
        # print("_configure_scrollCanvas:")
        # print("    event", "w=", event.width, "h", event.height)
        # print("    scrollCanvas", "w=", self.scrollCanvas.winfo_width(), ", h=", self.scrollCanvas.winfo_height())
        # print("    scrollWindow", "w=", self.scrollWindow.winfo_width(), ", h=", self.scrollWindow.winfo_height())
        # print("    scrollWindow reqwidth and reqheight", "w=", self.scrollWindow.winfo_reqwidth(), ", h=", self.scrollWindow.winfo_reqheight())
        #=======================================================================
        ##canvasWidth, canvasHeight = (self.scrollCanvas.winfo_width(), self.scrollCanvas.winfo_height())
        canvasWidth, canvasHeight = (event.width, event.height)
        windowReqWidth, windowReqHeight = (self.scrollWindow.winfo_reqwidth(), self.scrollWindow.winfo_reqheight())   
        if canvasWidth < windowReqWidth:
            if  canvasHeight < windowReqHeight:
                # canvasWidth < windowReqWidth and canvasHeight < windowReqHeight
                self.scrollCanvas.config(width = windowReqWidth, height = windowReqHeight)
                self.scrollCanvas.itemconfig(self.scrollWindowItemId, width=windowReqWidth, height=windowReqHeight)
                ##self.scrollCanvas.config(scrollregion='0 0 %s %s' % (windowReqWidth, windowReqHeight))
                self.scrollCanvas.config(scrollregion=self.scrollCanvas.bbox("all"))
                self.xScrollbar.grid()
                self.yScrollbar.grid()

            else:
                # canvasWidth < windowReqWidth and windowReqHeight <= canvasHeight
                self.scrollCanvas.config(width = windowReqWidth)
                self.scrollCanvas.itemconfig(self.scrollWindowItemId, width=windowReqWidth, height=canvasHeight)
                ##self.scrollCanvas.config(scrollregion='0 0 %s %s' % (windowReqWidth, canvasHeight))
                self.scrollCanvas.config(scrollregion=self.scrollCanvas.bbox("all"))
                self.xScrollbar.grid()
                self.tk.call("grid", "remove", self.yScrollbar)
        else: #  windowReqWidth <= canvasWidth
            if canvasHeight < windowReqHeight:
                # windowReqWidth <= canvasWidth and canvasHeight < windowReqHeigh
                self.scrollCanvas.config(height = windowReqHeight)
                self.scrollCanvas.itemconfig(self.scrollWindowItemId, width=canvasWidth, height=windowReqHeight)
                ##self.scrollCanvas.config(scrollregion='0 0 %s %s' % (canvasWidth, windowReqHeight))
                self.scrollCanvas.config(scrollregion=self.scrollCanvas.bbox("all"))
                self.tk.call("grid", "remove", self.xScrollbar)
                self.yScrollbar.grid()
            else:
                # windowReqWidth <= canvasWidth and windowReqHeight <= canvasHeight
                self.scrollCanvas.itemconfig(self.scrollWindowItemId, width=canvasWidth, height=canvasHeight)
                self.scrollCanvas.config(scrollregion=self.scrollCanvas.bbox("all"))
                self.tk.call("grid", "remove", self.xScrollbar)
                self.tk.call("grid", "remove", self.yScrollbar)

    def getScrollWindow(self):
        return self.scrollWindow

相关问题 更多 >