简体   繁体   中英

Problems with horizontal and vertical scrolling

I am writing a simple spreadsheet viewer. What I want is for row 0 to be controls and not scroll, Row 1 to be column headers and scroll horizontally with the data, rows 2 through end -1 to be data and scroll scroll both horizontally and vertically and a scroll bar at the far right, and the end row to be the horizontal scroll bar. I want the program to fill the entire window. What I have now is only the top left quarter of the window is used, horizontal scrolling works but there is no data and no vertical scroll bar.


import tkinter as tk
from tkinter import messagebox

class test:
    def __init__(self,root,hxw):
        self.hxw=hxw
        root.wm_title("Test")
        root.configure(bd=2)
        root.rowconfigure(0, weight = 1)
        root.columnconfigure(0, 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 = tk.Frame(self.top, height=25, background="blue") 
        self.topFrame.grid(row=0,column=0, sticky="NEW")
        self.topFrame.grid_columnconfigure(0, weight=1)
        self.topFrame.grid_rowconfigure(0, weight=1)
        tk.Button(self.topFrame, text="Help", command=self.callback4).grid(row=0, column=0, sticky='E')
        self.hsFrame = tk.Frame(self.top, background="red")
        self.hsFrame.grid(row=1,column=0, sticky="NEWS")
        self.hsFrame.grid_columnconfigure(0, weight=1)
        self.hsFrame.grid_rowconfigure(1, weight=1)
        self.hcanvas = tk.Canvas(self.hsFrame, background="green")
        self.hcanvas.grid(row=0, column=0, sticky="NEW")
        self.hcanvas.grid_columnconfigure(0, weight=1)
        self.hcanvas.grid_rowconfigure(0, weight=1)
        self.mFrame = tk.Frame(self.hcanvas)
        self.mFrame.grid(row=0, column=0)
        self.mFrame.grid_columnconfigure(0, weight=1)
        self.mFrame.grid_rowconfigure(0, weight=1)

        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 = tk.Frame(self.mFrame, background="grey")                    #place a frame on the canvas, this frame will hold the child widgets 
        self.labelFrame.grid(row=0,column=0, sticky="NEWS")      
        self.labelFrame.grid_rowconfigure(0, weight=1)
        self.labelFrame.grid_columnconfigure(0, weight=1)
        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 = tk.Frame(self.mFrame, background="yellow") 
        self.vsFrame.grid(row=1,column=0, sticky="NEWS")
        self.vsFrame.grid_rowconfigure(1, weight=1)
        self.vsFrame.grid_columnconfigure(0, weight=1)
        self.vcanvas = tk.Canvas(self.vsFrame, background="#ff00ff")
        self.vcanvas.grid(row=0,column=0, sticky="NEWS")                
        self.vcanvas.grid_rowconfigure(0, weight=1)
        self.vcanvas.grid_columnconfigure(0, weight=1)

        self.botFrame = tk.Frame(self.vcanvas, background="orange")                   #place a frame on the canvas, this frame will hold the child widgets 
        self.botFrame.grid(row=0,column=0, sticky="NEWS")                
        self.botFrame.grid_rowconfigure(0, weight=1)
        self.botFrame.grid_columnconfigure(0, weight=1)

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

        

To make your widgets fill the root window modify your code as below.

This is taken from your __init__ just after self.hxw=hxw

        root.wm_title("Test")
        root.configure(bd=2)
        root.rowconfigure(0, weight = 1)
        root.columnconfigure(0, weight = 1)

row and column configure can be applied directly to root just like any other container.

Ok, now you have a full screen view, the next step is to make your code easier to read so here is another code snippet that will help.

def flexx(o, r = 0, c = 0, rw = 1, cw = 1):
    if r !=  None:
        o.rowconfigure(r, weight = rw)
    if c !=  None:
        o.columnconfigure(c, weight = cw)

class test:

    def __init__(self,root,hxw):
        self.hxw = hxw
        root.wm_title("Test")
        root.configure(bd = 2)
        flexx(root)
        flexx(root, r =  1)

You should be able to use flexx on widgets that are currently using grid_rowconfigure and grid_columnconfigure . I've already replaced those without any apparent adverse effect. Note the way flexx is applied to root , this is pretty much how most other widgets are made flexible.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM