首页 > 解决方案 > 水平和垂直滚动的问题

问题描述

我正在编写一个简单的电子表格查看器。我想要的是第 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()

                

标签: pythontkinter

解决方案


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()

推荐阅读