【问题标题】:Problems with horizontal and vertical scrolling水平和垂直滚动的问题
【发布时间】:2021-07-29 07:15:48
【问题描述】:

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

                

【问题讨论】:

  • 你的问题是你没有将rowconfigure或者columnconfigure申请到root
  • 你不应该在一个小部件 (self.mFrame) 上调用.grid,如果它的主人是一个Canvas。尝试使用this。它就像一个普通的tkinter.Frame
  • 这是否记录在任何地方?它符合我的经验,但如果可以的话,我更喜欢使用网格。

标签: python tkinter


【解决方案1】:
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()

【讨论】:

  • 我添加了 rowconfigure 和 columnconfigure,现在窗口已完全填满。下一个问题是窗口中间出现了那一行列标题,仍然没有数据。
  • 我已经设法让蓝色、绿色和橙色对象可见按钮仍然无法查看按钮。我将附加我的答案以包含一个名为 flexx 的函数,它将减少您的程序的体积并使其更易于阅读。
  • 怎么样?您是否设法查看按钮和滚动条?我取得了一些成功,但很难解释。物体相互重叠存在许多问题。我设法查看按钮和所有三个滚动条。如果您想查看我正在工作的代码,请询问。
  • 我将代码更改为更具可读性。我会对你的代码感兴趣,但应该只有两个滚动条。如果您想查看我希望它的外观,请打开电子表格并冻结第一行。现在滚动条应该做我正在寻找的。​​span>
  • 好的,我把你的代码分成几个部分,发现第一部分几乎没有修改,而第二部分几乎相同,但有更多错误,所以我复制了第一部分 - 这就是额外滚动条的来源我现在将发布这些修改。 116行
猜你喜欢
  • 2022-08-14
  • 2014-01-09
  • 1970-01-01
  • 2015-02-10
  • 2019-01-25
  • 1970-01-01
  • 2020-08-17
  • 2015-05-31
  • 2013-11-30
相关资源
最近更新 更多