Tkinter框架网格垂直堆叠而非水平排列

-1 投票
1 回答
508 浏览
提问于 2025-04-18 10:32

我肯定对pack和grid这两个东西有些误解……

我正在为一个Python应用程序制作图形界面,这个程序会在多个像终端一样的控制台中显示调试信息。对我来说,使用Tkinter制作图形界面还是个新鲜事。

首先,为什么我需要用pack把按钮框架显示出来?难道grid不应该和pack是一样的吗?

这个图形界面上方有一系列按钮在按钮框架里,下面有一系列竖着的控制台显示在不同的列里。可是我得到的结果是所有控制台都垒在了一起,竖着堆放。

这些控制台是带有文本的框架,文本是由应用程序中的其他线程写入的。

如果我不使用grid来放置控制台[idx],它就不会改变(所以我猜这不管用)。如果我不使用pack来放置控制台[idx],图形界面就开始闪烁。

请注意,如果我调用create_Hterms,这个方法会把一堆横向的控制台竖着堆放在一起。

我该如何正确地把我的控制台放成竖列呢?

import Tkinter as tikei

NCONSOLES = 4
HORZ_CONSOLE_W = 10
HORZ_CONSOLE_H = 12

# FakeConsole: one of the consoles that are spawned by MainWindow.
class FakeConsole(tikei.Frame): # from Kevin in http://stackoverflow.com/questions/19479504/how-can-i-open-two-consoles-from-a-single-script
    def __init__(self, root, cust_width, cust_height, *args, **kargs):
        tikei.Frame.__init__(self, root, *args, **kargs)
        self.grid(row=0)

        #white text on black background
        self.text = tikei.Text(root, bg="black", fg="white", width=cust_width, height=cust_height)
        self.text.grid(row=0)
        self.text.insert(tikei.END, 'ASD')
        self.text.see(tikei.END)

    def clearConsole(self):
        self.text.delete(1.0,tikei.END)



class MainWindow(tikei.Frame):
    counter = 0
    consoles = []
    consoleFormat = ''
    e_Vvar = ''
    e_Hvar = ''
    var1 = ''
    ctrlCmdRecipient = ''

    def __init__(self, *args, **kwargs):
        tikei.Frame.__init__(self, *args, **kwargs)
        self.consoleFormat = 'H'
        self.cF = tikei.StringVar()

        self.grid(row=0)

        self.buttonframe = tikei.Frame(self)
        self.buttonframe.grid(row=0)
        tikei.Button(self.buttonframe, text = "Clear Consoles", command=self.clearConsoles).grid(row=0, column=0)
        tikei.Button(self.buttonframe, text = "start").grid(row=0, column=1)
        tikei.Button(self.buttonframe, text = "stop").grid(row=0, column=2)

        self.consoleFrame = tikei.Frame(self)

        self.create_Hterms()

        self.consoleFrame.grid(row=1)

        # create a status bar
        self.statusTxt = tikei.StringVar()
        self.statusTxt.set('-')
        self.statusLab = tikei.Label(self.buttonframe, text="Status: ", anchor=tikei.W, height=1).grid(row=1, column=0, sticky=tikei.W)
        self.statusBar = tikei.Label(self.buttonframe, textvariable=self.statusTxt, anchor=tikei.W, height=1).grid(row=1, column=1, columnspan=4, sticky=tikei.W)


    def clearConsoles(self):
        for i in range(NCONSOLES):
            self.consoles[i].clearConsole()

    def create_Hterms(self):
        ctr = NCONSOLES
        idx = 0

        cons_w = HORZ_CONSOLE_W
        cons_h = HORZ_CONSOLE_H

        while ctr > 0:
            self.consoles.append(FakeConsole(self.consoleFrame, cons_w, cons_h)) # 
            self.consoles[idx].grid(row=idx+1, column=0)
            ctr -= 1
            idx += 1
        return idx+1



root = tikei.Tk()
mainTk = MainWindow(root)
root.wm_title("TOOLS")
mainTk.grid(row=0)
root.mainloop()

1 个回答

0

首先,为什么我需要使用pack来显示buttonframe?难道grid不应该和pack是一样的吗?

其实,一般来说,你并不需要用pack来显示buttonframe。你可以选择用pack或者grid,但不要在同一个控件上同时使用这两种方法。不过在这个特定的情况下,使用pack掩盖了你代码中更深层次的问题,让人觉得调用pack是必须的。

问题在于你对self.consoleFrame使用了pack,而self.consoleFrameself.buttonFrame有相同的父控件。因为它们共享同一个父控件,所以你必须对这两个控件使用相同的方法,要么都用pack,要么都用grid。

这个界面是由上面的buttonframe中的一系列按钮和下面显示为列的垂直控制台组成。但我得到的结果是所有控制台都垂直堆叠在一起。

grid,然后又用了pack。你只能选择其中一个,最后使用的那个“胜出”。所以你现在在用pack,而且没有给它任何选项,所以它默认是从上到下排列的。

虽然在同一个应用程序中同时使用gridpack是完全安全的,但在同一个控件上使用这两者是没有意义的,而且对于共享同一个父控件的控件使用不同的方法是错误的。

解决这个问题的办法是要在使用gridpack时保持一致。如果你打算使用grid,那么确保对所有共享同一个父控件的控件都一致地使用它。

对于pack也是一样——要保持一致。此外,我建议你在使用pack时总是明确添加sidefillexpand这些参数,这样可以清楚地表达你的意图。

撰写回答