缩放 Tkinter 小部件

5

我正在使用Tkinter的"grid()"方法为我的Python程序设计GUI。

有没有办法让小部件随着主窗口进行缩放?

这里是一个简短的例子:

from Tkinter import *

master = Tk()

Label(master, text="This is a test").grid(row=0, column=0)

mytext1 = Text(master, width=30, height=5)
mytext1.grid(row=1, column=0)

mytext2 = Text(master, width=30, height=5)
mytext2.grid(row=3, column=0)

master.mainloop()

我希望实现当主窗口大小改变时,部件能够自动调整大小。(对于如此小的GUI而言,这不是问题,但当有很多部件时,这变得更加令人期望。)

非常感谢您的任何帮助!

2个回答

3

你需要配置行/列为 weight,这样当你调整窗口大小时它们才能够自动扩展。此外,你还需要将小部件设为其单元格边缘的 sticky。不仅 frame 的行/列需要设置 weight,而且 frame 中的所有行和列都需要设置 weight,因此需要使用 for 循环。

from Tkinter import *

class MyFrame(Frame):
    def __init__(self, master):
        Frame.__init__(self, master)
        self.grid(row=0, column=0, sticky=N+S+E+W)
        #Give the grid, column of the frame weight...
        Grid.rowconfigure(master, 0, weight=1)
        Grid.columnconfigure(master, 0, weight=1)
        self.create_widgets()

    def create_widgets(self):
        #Give the grid, column of each widget weight...
        for rows in xrange(3):
            Grid.rowconfigure(self, rows, weight=1)
        for columns in xrange(1):
            Grid.columnconfigure(self, columns, weight=1)

        self.label = Label(self, text="This is a test")
        self.label.grid(row=0, column=0, sticky=N+S+E+W)

        self.mytext1 = Text(self, width=30, height=5)
        self.mytext1.grid(row=1, column=0, sticky=N+S+E+W)

        self.mytext2 = Text(self, width=30, height=5)
        self.mytext2.grid(row=2, column=0, sticky=N+S+E+W)


root = Tk()
app = MyFrame(root)
root.mainloop()

您的基本框架长这样:
from Tkinter import *

#Sets up a frame
class MyApplication(Frame):

    #When a class is initialized, this is called as per any class 
    def __init__(self, master):

        #Similar to saying MyFrame = Frame(master)
        Frame.__init__(self, master)

        #Puts the frame on a grid. If you had two frames on one window, you would do the row, column keywords (or not...)
        self.grid()

        #Function to put the widgets on the frame. Can have any name!
        self.create_widgets()

    def create_widgets(self):
        label = Label(self, text='Hello World!')
        label.grid()

        button = Button(self, text='Press Me!', command=self.hello)
        button.grid()

   def hello(self):
        print "Hello World!"

root = Tk()
app = MyApplication(root)
root.mainloop()

任何Tkinter小部件都可以像这样处理,允许使用模板(我有一个程序,需要多个具有相同行为的输入框(单击清除默认文本,单击关闭如果没有输入则返回它),而不是将绑定添加到每个输入框中,我能够创建一个表现相同的输入框类),并且易于实现toplevels(附加窗口)。以下是一个更复杂程序的示例:
class IntroScreen(Frame):
    def __init__(self, master):
        Frame.__init__(self, master)
        self.grid()
        self.title('Intro Screen')
        self.create_widgets()
        self.focus_force()

    def create_widgets(self):
        label = Label(self, text='Hello World!')
        label.grid()

        button = Button(self, text='Open Window', command=self.newWindow)
        button.grid()

   def newWindow(self):
        self.toplevel = InfoWindow()

#Like the frame, or any widget, this inherited from the parent widget
class InfoWindow(Toplevel):
    def __init__(self):
        Toplevel.__init__(self)
        self.grid()
        self.create_widgets()
        self.focus_force()

    def create_widgets(self):
        label = Label(self, text='This is a window!')
        label.grid()

root = Tk()
app = IntroScreen(root)
root.mainloop()

正如您所看到的,这种功能的实现如果没有类会更加困难。如果您打算深入了解Tkinter强大的功能,请在stackoverflow上寻找更多答案(我推荐Bryan Oakley的众多且丰富的回答),并在网上进行一些研究!

PS:这里是一个很好的起点:在tkinter中在两个框架之间切换


能否在不将GUI放入类中的情况下完成这个操作? - CodingCat
@Lastalda,我认真考虑在Tkinter中使用类进行编程。如果没有额外的功能和组织便利性,很难制作除小型GUI之外的任何东西。如果你有兴趣,我已经编辑了我的答案,并提供了一些示例供你参考。 - Al.Sal

2

这里是没有使用类的相同内容。随着程序规模的增大,使用类更加清晰明了。请注意,我将标签的权重设置为0,这可以防止其扩展。您不必这样做,因为它是默认选项。这只是为了让您知道您可以做什么。

有关网格布局管理器的更多详细信息:http://www.tkdocs.com/tutorial/grid.html

from Tkinter import *

master = Tk()

Label(master, text="This is a test").grid(row=0, column=0)

mytext1 = Text(master, width=30,height=5)
mytext1.grid(row=1, column=0, sticky="nsew")

mytext2 = Text(master, width=30,height=5)
mytext2.grid(row=2, column=0, sticky="nsew")

master.columnconfigure(0, weight=1)
master.rowconfigure(0, weight=0) # not needed, this is the default behavior
master.rowconfigure(1, weight=1)
master.rowconfigure(2, weight=1)

master.mainloop()

非常感谢!我知道使用类来创建GUI应该更容易,但是它让我感到非常困惑。 - CodingCat
1
要理解如何在Tkinter中使用类,您需要对继承有很好的掌握。然而,我认为在Tkinter中展示如何做事情的非类示例更加简洁易读。您并不是在问如何使用Tkinter开发大型应用程序,而只是想要完成一件简单的事情。答案越简单越好,因为它只显示了您所要求的内容,没有多余的东西。 - tylerjw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接