【问题标题】:Issues with layout management in Tkinter Python applicationTkinter Python 应用程序中的布局管理问题
【发布时间】:2014-03-24 02:07:35
【问题描述】:

关于窗口上控件的布局,我在 Python 中制作的一个 Tkinter 小程序作为我自己的 CMS 的前端遇到了一个真正的问题。我是 Tkinter 的新手,但不是 Python,但我正在努力使用网格布局管理器来安排我想要的控件。 这是我的目标的(可怕的)模型:

但我的代码(如下)仅呈现:

这是我的代码:

'''
Configure main window controls
'''
postTtlFrame = Frame(tkRoot, bg="red")
postTtlLbl = Label(postTtlFrame, text="Page title:").grid(row=0, column=0)
postTtlEnt = Entry(postTtlFrame).grid(row=0, column=1)
postTtlFrame.grid(row=0, column=0)

postTxtFrame = Frame(tkRoot, bg="blue")
postTxtLbl = Label(postTxtFrame, text="Page body content:").grid(row=0, column=0)
postTxtArea = Text(postTxtFrame).grid(row=1, columnspan=1)
postTxtFrame.grid(row=1, column=0)

pageConfigFrame = Frame(tkRoot, bg="green")
headerDirecLbl = Label(tkRoot, text="Page header location:").grid(row=0, column=0)
headerDirecEnt = Entry(tkRoot).grid(row=0, column=1)
footerDirecLbl = Label(tkRoot, text="Page footer location:").grid(row=1, column=0)
footerDirecEnt = Entry(tkRoot).grid(row=1, column=1)
stylesDirecLbl = Label(tkRoot, text="Page stylesheet location:").grid(row=2, column=0)
stylesDirecEnt = Entry(tkRoot).grid(row=2, column=1)
outputDirecLbl = Label(tkRoot, text="Page output location:").grid(row=3, column=0)
outputDirecEnt = Entry(tkRoot).grid(row=3, column=1)
pageConfigFrame.grid(row=2, column=0)

buttonsFrame = Frame(tkRoot, bg="orange")
postBtn = Button(tkRoot, text="Post").grid(row=0, column=0)
exitBtn = Button(tkRoot, text="Exit", command=quitTk).grid(row=0, column=1)
buttonsFrame.grid(row=3, column=0)

请有人向我解释到底出了什么问题!

提前致谢, 伊尔蒙

【问题讨论】:

    标签: python user-interface layout tkinter


    【解决方案1】:

    是的,我现在可以工作了@jeanrjc,我的代码充满了我现在意识到的错误;这是我最后使用的:

    '''
    Configure main window controls
    '''
    postTtlFrame = Frame(tkRoot)
    postTtlLbl = Label(postTtlFrame, text="Page title:").grid(row=0, column=0)
    postTtlEnt = Entry(postTtlFrame).grid(row=0, column=1)
    postTtlFrame.grid(row=0, column=0, sticky=W)
    
    postTxtFrame = Frame(tkRoot)
    postTxtLbl = Label(postTxtFrame, text="Page body content:").grid(row=0, column=0, sticky=W)
    postTxtArea = Text(postTxtFrame).grid(row=1, columnspan=1)
    postTxtFrame.grid(row=1, column=0, sticky=W)
    
    pageConfigFrame = Frame(tkRoot)
    headerDirecLbl = Label(pageConfigFrame, text="Page header location:").grid(row=0, column=0, sticky=W)
    headerDirecEnt = Entry(pageConfigFrame).grid(row=0, column=1)
    footerDirecLbl = Label(pageConfigFrame, text="Page footer location:").grid(row=1, column=0, sticky=W)
    footerDirecEnt = Entry(pageConfigFrame).grid(row=1, column=1)
    stylesDirecLbl = Label(pageConfigFrame, text="Page stylesheet location:").grid(row=2, column=0, sticky=W)
    stylesDirecEnt = Entry(pageConfigFrame).grid(row=2, column=1)
    outputDirecLbl = Label(pageConfigFrame, text="Page output location:").grid(row=3, column=0, sticky=W)
    outputDirecEnt = Entry(pageConfigFrame).grid(row=3, column=1)
    pageConfigFrame.grid(row=2, column=0, sticky=W)
    
    buttonsFrame = Frame(tkRoot)
    postBtn = Button(buttonsFrame, text="Post").grid(row=0, column=0)
    exitBtn = Button(buttonsFrame, text="Exit", command=quitTk).grid(row=0, column=1)
    buttonsFrame.grid(row=3, column=0, sticky=E)
    

    现在我得到了我想要的以下结果:

    不过还是谢谢!

    【讨论】:

      【解决方案2】:

      首先,如果您同时调用grid(或packplace),则将小部件分配给变量是没有意义的。 foo=Label(..).grid(...) 将始终返回 None,因为 grid(...) 始终返回 None。此外,我发现将布局与小部件创建分开时,布局问题要容易得多解决。

      那么,让我们开始吧:

      '''
      Configure main window controls
      '''
      postTtlFrame = Frame(tkRoot, bg="red")
      postTxtFrame = Frame(tkRoot, bg="blue")
      pageConfigFrame = Frame(tkRoot, bg="green")
      buttonsFrame = Frame(tkRoot, bg="orange")
      
      postTtlFrame.grid(row=0, column=0)
      postTxtFrame.grid(row=1, column=0)
      pageConfigFrame.grid(row=2, column=0)
      buttonsFrame.grid(row=3, column=0)
      
      postTtlLbl = Label(postTtlFrame, text="Page title:")
      postTtlEnt = Entry(postTtlFrame).grid(row=0, column=1)
      postTtlLbl.grid(row=0, column=0)
      
      postTxtLbl = Label(postTxtFrame, text="Page body content:")
      postTxtArea = Text(postTxtFrame)
      postTxtLbl.grid(row=0, column=0)
      postTxtArea.grid(row=1, columnspan=1)
      
      headerDirecLbl = Label(tkRoot, text="Page header location:")
      headerDirecEnt = Entry(tkRoot)
      footerDirecLbl = Label(tkRoot, text="Page footer location:")
      footerDirecEnt = Entry(tkRoot)
      stylesDirecLbl = Label(tkRoot, text="Page stylesheet location:")
      stylesDirecEnt = Entry(tkRoot)
      outputDirecLbl = Label(tkRoot, text="Page output location:")
      outputDirecEnt = Entry(tkRoot)
      postBtn = Button(tkRoot, text="Post")
      exitBtn = Button(tkRoot, text="Exit")
      
      headerDirecLbl.grid(row=0, column=0)
      headerDirecEnt.grid(row=0, column=1)
      footerDirecLbl.grid(row=1, column=0)
      footerDirecEnt.grid(row=1, column=1)
      stylesDirecLbl.grid(row=2, column=0)
      stylesDirecEnt.grid(row=2, column=1)
      outputDirecLbl.grid(row=3, column=0)
      outputDirecEnt.grid(row=3, column=1)
      postBtn.grid(row=0, column=0)
      exitBtn.grid(row=0, column=1)
      

      现在,我认为您可以更清楚地看到正在发生的事情。我看到的问题是:

      1. 您似乎想将事物组织成四个主要区域,但您的模型显示前三个区域中的所有内容都应该共享相同的网格结构,所以我不确定您为什么要创建这些框架李>
      2. 您不会为行或列分配任何权重,因此它们不会按照您的预期增长和缩小
      3. 大多数小部件都共享 tkRoot 的共同父级,而不是您创建的组织框架,因此这些框架最终毫无用处
      4. 由于许多小部件共享同一个父级,因此您最终会将多个小部件彼此叠加在同一个网格单元中。
      5. 您不使用sticky 属性,因此小部件不会填充它们的列。

      解决所有这些问题的方法取决于您想要达到的效果。如果您想要四个独立的区域,您需要确保每个小部件都有适合其父级的框架,而不是将大多数小部件集中在 tkRoot 框架中。例如,这很可能导致 postTtlEnt 不会与其他条目小部件对齐。

      如果您想要四个独立的区域并且确实希望 postTtlEnt 小部件与其他所有内容对齐,请去掉中间帧并将所有内容放入一个单格。

      您可能想要混合使用——按钮不一定需要共享同一个网格,但所有条目小部件应该共享同一个网格。这就是我将如何做到的。请注意,我只有一个额外的内部框架,用于按钮。其他一切都有一个共同的父母。另请注意,我为一行和一列赋予了权重,以便您获得正确的调整大小行为:

      这是一个完整的工作示例。它与您的模型不完全匹配:退出和发布按钮没有自己的专用列,但如果您真的想要,您可以这样做。按钮上方的空间似乎被浪费了,所以我选择将按钮直接放在输入小部件的下方。

      '''
      Configure main window controls
      '''
      
      postTtlLbl = Label(tkRoot, text="Page title:")
      postTxtLbl = Label(tkRoot, text="Page body content:")
      headerDirecLbl = Label(tkRoot, text="Page header location:")
      footerDirecLbl = Label(tkRoot, text="Page footer location:")
      stylesDirecLbl = Label(tkRoot, text="Page stylesheet location:")
      outputDirecLbl = Label(tkRoot, text="Page output location:")
      
      postTtlEnt = Entry(tkRoot)
      postTxtArea = Text(tkRoot)
      footerDirecEnt = Entry(tkRoot)
      headerDirecEnt = Entry(tkRoot)
      stylesDirecEnt = Entry(tkRoot)
      outputDirecEnt = Entry(tkRoot)
      
      buttonsFrame = Frame(tkRoot, bg="orange")
      postBtn = Button(buttonsFrame, text="Post")
      exitBtn = Button(buttonsFrame, text="Exit")
      postBtn.pack(side="right")
      exitBtn.pack(side="right")
      
      postTtlLbl.grid(row=0, column=0, sticky="w")
      postTxtLbl.grid(row=1, column=0, sticky="w")
      headerDirecLbl.grid(row=3, column=0, sticky="w")
      footerDirecLbl.grid(row=4, column=0, sticky="w")
      stylesDirecLbl.grid(row=5, column=0, sticky="w")
      outputDirecLbl.grid(row=6, column=0, sticky="w")
      
      postTtlEnt.grid(row=0, column=1, sticky="ew")
      postTxtArea.grid(row=2, column=0, columnspan=2, sticky="nsew")
      headerDirecEnt.grid(row=3, column=1, sticky="ew")
      footerDirecEnt.grid(row=4, column=1, sticky="ew")
      stylesDirecEnt.grid(row=5, column=1, sticky="ew")
      outputDirecEnt.grid(row=6, column=1, sticky="ew")
      buttonsFrame.grid(row=7, column=0, sticky="ew", columnspan=2)
      
      tkRoot.grid_rowconfigure(2, weight=1)
      tkRoot.grid_columnconfigure(1, weight=1)
      

      【讨论】:

        【解决方案3】:

        我设法得到非常接近你想要的东西:

        from Tkinter import *
        
        root = Tk()
        content = Label(root, padx=30,pady=30,background = "white")
        content.grid(column=0, row=0, sticky=(N, S, E, W))
        title_frame = Label(content, borderwidth=5, relief="sunken", padx=30,pady=30,background = "white")
        title_frame.grid(column=0, row=0, sticky=(N))
        body_frame = Label(content, borderwidth=5, relief="sunken", padx=30,pady=30,background = "white")
        body_frame.grid(column=0, row=1, sticky=(N,W,E))
        config_frame = Label(content, borderwidth=5, relief="sunken", padx=30,pady=30,background = "white")
        config_frame.grid(column=0, row=2, sticky=(N, W))
        button_frame = Label(content, borderwidth=5, relief="sunken", padx=30,pady=30,background = "orange")
        button_frame.grid(column=1, row=2, sticky=(S, E))
        
        title_entry = Entry(title_frame, background="lightblue")
        title_entry.grid(column=1, row=0)
        title_label = Label(title_frame,text = "Page title",background = "white")
        title_label.grid(column=0,row=0)
        
        body_text = Text(body_frame, background="lightblue")
        body_text.grid(column=1,row=0)
        body_label = Label(body_frame,text = "Page body content",background = "white")
        body_label.grid(column=0, row=0)
        
        header_entry = Entry(config_frame, background="lightblue")
        header_entry.grid(column=1, row=0)
        header_label = Label(config_frame,text = "header",background = "white")
        header_label.grid(column=0,row=0)
        
        footer_entry = Entry(config_frame, background="lightblue")
        footer_entry.grid(column=1, row=1)
        footer_label = Label(config_frame,text = "footer",background = "white")
        footer_label.grid(column=0,row=1)
        
        postBtn = Button(button_frame, text="Post")
        postBtn.grid(row=0, column=0)
        exitBtn = Button(button_frame, text="Exit")
        exitBtn.grid(row=0, column=1)
        

        它显示:

        关于为什么您的代码不起作用: 我想这是因为你定义了你的网格位置:

        postTtlLbl = Label(postTtlFrame, text="Page title:").grid(row=0, column=0)
        

        代替

         postTtlLbl = Label(postTtlFrame, text="Page title:")
         postTtlLbl.grid(row=0, column=0)
        

        当您希望创建框架的实例时(通过将实例返回到 postTtlLbl 变量中),这是一个问题,因为 grid 方法不返回任何内容,因此这些处理框架的变量是 Nonetype,并且你不能对他们做任何事情。

        希望清楚。

        【讨论】:

        • 我认为这是一个糟糕的答案。它没有解决代码中的许多问题,并且给出了与预期结果不匹配的最终结果。页眉、页脚和页面标题的对齐方式已关闭。最后,当您更改包含窗口的大小时,GUI 无法正确调整大小。
        • 它解决了问题的作者提出的问题:“我正在努力使用网格布局管理器来按我的意愿排列我的控件”。
        • 我想我应该改写我的评论。我的意思是,这是一个好的开始,但是如果您准确地解释原始代码的问题,您可以使答案变得更好。虽然在小部件创建期间调用 .grid 是 a 问题,但它并没有真正促成这个问题中的问题。简单地说“这是一个工作示例”,然后让这个工作示例稍微好一点,并不能得到一个很好的答案。通过一点努力,我认为您可以使这个答案变得更好。
        猜你喜欢
        • 2017-12-24
        • 2020-01-04
        • 2013-05-11
        • 1970-01-01
        • 2013-03-24
        • 2013-05-03
        • 2023-03-30
        • 2021-06-21
        • 2011-09-05
        相关资源
        最近更新 更多