如何将小部件放在使用pack并排的小部件下面?

时间:2018-02-09 19:47:39

标签: python tkinter

我试着像这样放置小部件:

enter image description here

我不明白为什么我的代码没有这样做,试图在线查找示例但是没有找到解决方案,我尝试的任何内容都没有让我更接近所要求的结果。

这是我的代码到目前为止(如果您对代码中的任何内容有任何意见,请随时告诉我,因为它是我第一次尝试使用和GUI):

from Tkinter import *


class box(object):

    def __init__ (self, colour,s):
        self.root = root
        self.listbox = Listbox(self.root, fg = colour, bg = 'black')
        self.s = s
        self.place_scrollbar()
        self.listbox.pack(side = self.s)


    def place_scrollbar(self):
        scrollbar = Scrollbar(self.root)
        scrollbar.pack(side = self.s, fill = Y)
        self.listbox.config(yscrollcommand = scrollbar.set)
        scrollbar.config(command = self.listbox.yview)

    def write(self, contenet):
        self.listbox.insert(END, contenet)

root = Tk()
root.resizable(False, False)
boxs = Frame(root)
boxs.pack()
box.root = boxs
server = box("red", LEFT)
client = box("green", RIGHT )
bf = Frame(root)
bf.pack(side = BOTTOM)
entry = Entry(bf,bg ='black', fg = 'white')
entry.pack()
root.mainloop()

2 个答案:

答案 0 :(得分:2)

can't do this在使用pack的情况下不使用其他框架来包含box个对象,同时仍保持可恢复性。

但在某些情况下,它更有条理:使用其他框架来包含box个对象,方法是使用父选项初始化它。

现在box类中的小部件是全局 root对象的子元素。这不是一个好习惯。因此,让我们首先通过并使用父对象来用于内部的小部件。

替换:

def __init__ (self, colour,s):
    self.root = root
    self.listbox = Listbox(self.root, ...)
    ...


def place_scrollbar(self):
    scrollbar = Scrollbar(self.root)
    ...

使用:

def __init__ (self, parent, colour,s):
    self.parent= parent
    self.listbox = Listbox(self.parent, ...)
    ...


def place_scrollbar(self):
    scrollbar = Scrollbar(self.parent)
    ...

这使得您现在需要初始化对象,如下所示:

server = box(root, "red", LEFT)
client = box(root, "green", RIGHT )

现在我们可以传递父窗口小部件,让我们创建一个父框架来包含它们。实际上,已经有一个未使用的框架,boxs让我们通过将其作为父框架而不是root来使用它:

server = box(boxs, "red", LEFT)
client = box(boxs, "green", RIGHT )

现在一切看起来都很好,可选择如果您想要使条目占用尽可能多的剩余空间,那么当前将fill='x'作为选项添加到条目和框架的pack包含它:

bf.pack(side = BOTTOM, fill='x')
...
entry.pack(fill='x')

您的整个代码应如下所示:

from Tkinter import *


class box(object):

    def __init__ (self, parent, colour,s):
        self.parent = parent
        self.listbox = Listbox(self.parent, fg = colour, bg = 'black')
        self.s = s
        self.place_scrollbar()
        self.listbox.pack(side = self.s)


    def place_scrollbar(self):
        scrollbar = Scrollbar(self.parent)
        scrollbar.pack(side = self.s, fill = Y)
        self.listbox.config(yscrollcommand = scrollbar.set)
        scrollbar.config(command = self.listbox.yview)

    def write(self, contenet):
        self.listbox.insert(END, contenet)

root = Tk()
root.resizable(False, False)
boxs = Frame(root)
boxs.pack()
box.root = boxs
server = box(boxs, "red", LEFT)
client = box(boxs, "green", RIGHT )
bf = Frame(root)
bf.pack(side = BOTTOM, fill='x')
entry = Entry(bf,bg ='black', fg = 'white')
entry.pack(fill='x')
root.mainloop()

或:使用grid代替packcolumnspan=2选项进行输入)。

一般答案

更一般地说,将小部件放在两个并排的小部件之下可以通过以下方式完成:

使用frame封装并排小部件,然后将frame放在其他小部件上方:

try:                        # In order to be able to import tkinter for
    import tkinter as tk    # either in python 2 or in python 3
except ImportError:
    import Tkinter as tk


def main():
    root = tk.Tk()
    side_by_side_widgets = dict()
    the_widget_beneath = tk.Entry(root)
    frame = tk.Frame(root)
    for name in {"side b", "y side"}:
        side_by_side_widgets[name] = tk.Label(frame, text=name)
        side_by_side_widgets[name].pack(side='left', expand=True)
    frame.pack(fill='x')
    the_widget_beneath.pack()
    root.mainloop()


if __name__ == '__main__':
    main()

使用grid

try:                        # In order to be able to import tkinter for
    import tkinter as tk    # either in python 2 or in python 3
except ImportError:
    import Tkinter as tk


def main():
    root = tk.Tk()
    side_by_side_widgets = dict()
    the_widget_beneath = tk.Entry(root)
    for index, value in enumerate({"side b", "y side"}):
        side_by_side_widgets[value] = tk.Label(root, text=value)
        side_by_side_widgets[value].grid(row=0, column=index)
    the_widget_beneath.grid(row=1, column=0, columnspan=2)
    root.mainloop()


if __name__ == '__main__':
    main()

在不使用其他框架的情况下,通过pack调用the_widget_beneath side='bottom'作为第一个pack来电,与Bryan's comment中一样:

try:                        # In order to be able to import tkinter for
    import tkinter as tk    # either in python 2 or in python 3
except ImportError:
    import Tkinter as tk


def main():
    root = tk.Tk()
    side_by_side_widgets = dict()
    the_widget_beneath = tk.Entry(root)
    the_widget_beneath.pack(side='bottom')
    for name in {"side b", "y side"}:
        side_by_side_widgets[name] = tk.Label(root, text=name)
        side_by_side_widgets[name].pack(side='left', expand=True)
    root.mainloop()


if __name__ == '__main__':
    main()

您可以通过创建全局main方法更轻松地注意全局对象的可靠性,并在其中添加脚本主体并调用:

...
def main():
    root = Tk()
    root.resizable(False, False)
    boxs = Frame(root)
    boxs.pack()
    box.root = boxs
    server = box(boxs, "red", LEFT)
    client = box(boxs, "green", RIGHT )
    bf = Frame(root)
    bf.pack(side = BOTTOM, fill='x')
    entry = Entry(bf,bg ='black', fg = 'white')
    entry.pack(fill='x')
    root.mainloop()

if __name__ == '__main__':
    main()

答案 1 :(得分:1)

  

如何将小部件放在两个使用pack并排的小部件下面?

对于图表中非常简单的布局,您只需先将物品打包在底部。那是因为pack使用了"腔#34;模型。每个小部件都组织在一个未填充的空腔中。放置该窗口小部件后,腔体的该部分将被填充,并且不可用于任何其他窗口小部件。

在您的情况下,您希望底部空腔填充条目小部件,因此您应该先打包它。然后,在剩余的上腔中,您可以并排放置两个框架,一个在左侧,一个在右侧。

例如:

import Tkinter as tk

root = tk.Tk()

entry = tk.Entry(root)
frame1 = tk.Frame(root, width=100, height=100, background="red")
frame2 = tk.Frame(root, width=100, height=100, background="green")

entry.pack(side="bottom", fill="x")
frame1.pack(side="left", fill="both", expand=True)
frame2.pack(side="right", fill="both", expand=True)

root.mainloop()

在你的问题正文中,事情变得有点复杂,因为你不像你的标题所暗示的那样只有三个小部件,你有几个,有些被打包在根中,有些被打包在其他地方, pack陈述遍布各处。

使用pack时,最好将小部件分组为垂直或水平切片,而不是在同一组内左右混合顶部/底部。看起来你似乎正试图用你的盒子做这件事,但是你不要 - 你的盒子"实际上是两个小部件。

底线:有条理。如果给定父级的所有pack(或placegrid)语句都在同一代码块中,那么它确实非常有用。当你将它们分散时,就无法实现可视化,也无法修复。此外,请确保窗口小部件具有适当的父窗口。