Tkinter框架网格垂直堆叠而非水平排列
我肯定对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 个回答
首先,为什么我需要使用pack来显示buttonframe?难道grid不应该和pack是一样的吗?
其实,一般来说,你并不需要用pack来显示buttonframe。你可以选择用pack或者grid,但不要在同一个控件上同时使用这两种方法。不过在这个特定的情况下,使用pack
掩盖了你代码中更深层次的问题,让人觉得调用pack
是必须的。
问题在于你对self.consoleFrame
使用了pack
,而self.consoleFrame
和self.buttonFrame
有相同的父控件。因为它们共享同一个父控件,所以你必须对这两个控件使用相同的方法,要么都用pack,要么都用grid。
这个界面是由上面的buttonframe中的一系列按钮和下面显示为列的垂直控制台组成。但我得到的结果是所有控制台都垂直堆叠在一起。
grid,然后又用了pack
。你只能选择其中一个,最后使用的那个“胜出”。所以你现在在用pack
,而且没有给它任何选项,所以它默认是从上到下排列的。
虽然在同一个应用程序中同时使用grid
和pack
是完全安全的,但在同一个控件上使用这两者是没有意义的,而且对于共享同一个父控件的控件使用不同的方法是错误的。
解决这个问题的办法是要在使用grid
和pack
时保持一致。如果你打算使用grid
,那么确保对所有共享同一个父控件的控件都一致地使用它。
对于pack
也是一样——要保持一致。此外,我建议你在使用pack
时总是明确添加side
、fill
和expand
这些参数,这样可以清楚地表达你的意图。