强制 TKinter 按钮输出到 window 的底部?
Forcing TKinter button output to bottom of window?
我对使用 TKinter 还很陌生。我正在制作一个显示 wine quality data sets 的描述性统计信息的 TKinter window。我遇到的问题是定位。即使使用 pack(side=BOTTOM)
,直方图按钮也会显示在我拥有的列选项按钮旁边,如下所示:
理想情况下,我希望 window 看起来像这样:
我尝试在制作标签“描述性统计”的同一位置制作按钮,然后稍后对其进行配置,但是虽然按钮保持在我想要的位置,但直方图最终还是一样地点。
编辑: 我最初使用 grid()
手动放置所有内容,但是出于美观原因,我不喜欢按钮之间的空格随着更多对象添加到 window 进行调整。我也收到了“不能使用 pack()
和 grid()
”的警告,即使我已将所有 pack()
更改为 grid()
,特别是因为我的绘图功能,我想不通。所以最后我只是从 grid()
切换到 pack()
以避免不断出现该错误。
我的代码:
import tkinter as tk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
#the main window
root = tk.Tk()
root.title('Descriptive statistics for vinho verde datasets')
#generate some labels
lbl1 = tk.Label(root, text = "Wine choice:")
lbl1.pack(side=TOP)
lbl2 = tk.Label(root, text = "Descriptive statistics:")
lbl2.pack(side=BOTTOM)
def wine_choice(opt):
#functions determining for which columns to output descriptive statistics
def describe(colm):
if opt == 'white':
res = white[colm].describe()
else:
res = red[colm].describe()
txt = "\nDescriptive statistics for {0} wine, {1}:\n\n{2}"
lbl2.config(text = txt.format(opt,colm,res))
def b_plot():
#figure that will contain the plot
fig = Figure(figsize = (5, 5), dpi = 75)
p1 = fig.add_subplot()
if opt == 'white':
p1.hist(white[colm])
else:
p1.hist(red[colm])
#creating the canvas containing figure and placing on the window
canvas = FigureCanvasTkAgg(fig, root)
canvas.draw()
canvas.get_tk_widget().pack(side=BOTTOM)
btn_p = tk.Button(root, command = b_plot, width=10, height=3, text = "Histogram").pack(side=BOTTOM)
lbl3 = tk.Label(root, text = "Pick an attribute to investigate:")
lbl3.pack(side=TOP)
#spawn attribute buttons after user chooses a wine
#generate buttons
btn3 = tk.Button(root, text='fixed acidity', width=10, height=3)
btn3.pack(side=LEFT)
btn3.bind('<Button-1>', lambda e: describe('fixed acidity'))
btn4 = tk.Button(root, text='volatile\nacidity', width=10, height=3)
btn4.pack(side=LEFT)
btn4.bind('<Button-1>', lambda e: describe('volatile acidity'))
btn5 = tk.Button(root, text='citric\nacid', width=10, height=3)
btn5.pack(side=LEFT)
btn5.bind('<Button-1>', lambda e: describe('citric acid'))
btn6 = tk.Button(root, text='residual\nsugar', width=10, height=3)
btn6.pack(side=LEFT)
btn6.bind('<Button-1>', lambda e: describe('residual sugar'))
btn7 = tk.Button(root, text='chlorides', width=10, height=3)
btn7.pack(side=LEFT)
btn7.bind('<Button-1>', lambda e: describe('chlorides'))
btn8 = tk.Button(root, text='free\nsulfur\ndioxide', width=10, height=3)
btn8.pack(side=LEFT)
btn8.bind('<Button-1>', lambda e: describe('free sulfur dioxide'))
btn9 = tk.Button(root, text='total\nsulfur\ndioxide', width=10, height=3)
btn9.pack(side=LEFT)
btn9.bind('<Button-1>', lambda e: describe('total sulfur dioxide'))
btn10 = tk.Button(root, text='density', width=10, height=3)
btn10.pack(side=LEFT)
btn10.bind('<Button-1>', lambda e: describe('density'))
btn11 = tk.Button(root, text='pH', width=10, height=3)
btn11.pack(side=LEFT)
btn11.bind('<Button-1>', lambda e: describe('pH'))
btn12 = tk.Button(root, text='sulphates', width=10, height=3)
btn12.pack(side=LEFT)
btn12.bind('<Button-1>', lambda e: describe('sulphates'))
btn13 = tk.Button(root, text='alcohol', width=10, height=3)
btn13.pack(side=LEFT)
btn13.bind('<Button-1>', lambda e: describe('alcohol'))
btn14 = tk.Button(root, text='quality', width=10, height=3)
btn14.pack(side=LEFT)
btn14.bind('<Button-1>', lambda e: describe('quality'))
#buttons for wine choices
btn1 = tk.Button(root, text = "white", width=10, height=2)
btn1.pack(side=TOP)
#remember which button user picks
btn1.bind('<Button-1>', lambda e: wine_choice('white'))
btn2 = tk.Button(root, text = "red", width=10, height=2)
btn2.pack(side=TOP)
btn2.bind('<Button-1>', lambda e: wine_choice('red'))
#must be called for window to be drawn and events to be processed
root.mainloop()
解决方案是将您的 UI 分成逻辑组,并使用框架来组织逻辑组。您可以让现有的东西发挥作用,但使用框架来组织小部件要容易得多。
我大概看到四个逻辑组:
- 一组两个垂直堆叠的按钮
- 十几个垂直排列的按钮
- 带有“直方图”按钮的统计块
- 直方图
因此,首先创建四个框架,每个部分一个。垂直堆叠最好使用 pack
.
完成后,将各种小部件放入其中一个框架中。从布局角度来看,每个框架都是独立的,因此您可以在每个框架中使用 grid
或 pack
。虽然,由于每个组似乎都是垂直或水平分组,pack
可能在所有情况下都效果最好,因为它在 left-to-right 和 top-to-bottom 布局方面表现出色,代码行最少。
我对使用 TKinter 还很陌生。我正在制作一个显示 wine quality data sets 的描述性统计信息的 TKinter window。我遇到的问题是定位。即使使用 pack(side=BOTTOM)
,直方图按钮也会显示在我拥有的列选项按钮旁边,如下所示:
理想情况下,我希望 window 看起来像这样:
我尝试在制作标签“描述性统计”的同一位置制作按钮,然后稍后对其进行配置,但是虽然按钮保持在我想要的位置,但直方图最终还是一样地点。
编辑: 我最初使用 grid()
手动放置所有内容,但是出于美观原因,我不喜欢按钮之间的空格随着更多对象添加到 window 进行调整。我也收到了“不能使用 pack()
和 grid()
”的警告,即使我已将所有 pack()
更改为 grid()
,特别是因为我的绘图功能,我想不通。所以最后我只是从 grid()
切换到 pack()
以避免不断出现该错误。
我的代码:
import tkinter as tk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
#the main window
root = tk.Tk()
root.title('Descriptive statistics for vinho verde datasets')
#generate some labels
lbl1 = tk.Label(root, text = "Wine choice:")
lbl1.pack(side=TOP)
lbl2 = tk.Label(root, text = "Descriptive statistics:")
lbl2.pack(side=BOTTOM)
def wine_choice(opt):
#functions determining for which columns to output descriptive statistics
def describe(colm):
if opt == 'white':
res = white[colm].describe()
else:
res = red[colm].describe()
txt = "\nDescriptive statistics for {0} wine, {1}:\n\n{2}"
lbl2.config(text = txt.format(opt,colm,res))
def b_plot():
#figure that will contain the plot
fig = Figure(figsize = (5, 5), dpi = 75)
p1 = fig.add_subplot()
if opt == 'white':
p1.hist(white[colm])
else:
p1.hist(red[colm])
#creating the canvas containing figure and placing on the window
canvas = FigureCanvasTkAgg(fig, root)
canvas.draw()
canvas.get_tk_widget().pack(side=BOTTOM)
btn_p = tk.Button(root, command = b_plot, width=10, height=3, text = "Histogram").pack(side=BOTTOM)
lbl3 = tk.Label(root, text = "Pick an attribute to investigate:")
lbl3.pack(side=TOP)
#spawn attribute buttons after user chooses a wine
#generate buttons
btn3 = tk.Button(root, text='fixed acidity', width=10, height=3)
btn3.pack(side=LEFT)
btn3.bind('<Button-1>', lambda e: describe('fixed acidity'))
btn4 = tk.Button(root, text='volatile\nacidity', width=10, height=3)
btn4.pack(side=LEFT)
btn4.bind('<Button-1>', lambda e: describe('volatile acidity'))
btn5 = tk.Button(root, text='citric\nacid', width=10, height=3)
btn5.pack(side=LEFT)
btn5.bind('<Button-1>', lambda e: describe('citric acid'))
btn6 = tk.Button(root, text='residual\nsugar', width=10, height=3)
btn6.pack(side=LEFT)
btn6.bind('<Button-1>', lambda e: describe('residual sugar'))
btn7 = tk.Button(root, text='chlorides', width=10, height=3)
btn7.pack(side=LEFT)
btn7.bind('<Button-1>', lambda e: describe('chlorides'))
btn8 = tk.Button(root, text='free\nsulfur\ndioxide', width=10, height=3)
btn8.pack(side=LEFT)
btn8.bind('<Button-1>', lambda e: describe('free sulfur dioxide'))
btn9 = tk.Button(root, text='total\nsulfur\ndioxide', width=10, height=3)
btn9.pack(side=LEFT)
btn9.bind('<Button-1>', lambda e: describe('total sulfur dioxide'))
btn10 = tk.Button(root, text='density', width=10, height=3)
btn10.pack(side=LEFT)
btn10.bind('<Button-1>', lambda e: describe('density'))
btn11 = tk.Button(root, text='pH', width=10, height=3)
btn11.pack(side=LEFT)
btn11.bind('<Button-1>', lambda e: describe('pH'))
btn12 = tk.Button(root, text='sulphates', width=10, height=3)
btn12.pack(side=LEFT)
btn12.bind('<Button-1>', lambda e: describe('sulphates'))
btn13 = tk.Button(root, text='alcohol', width=10, height=3)
btn13.pack(side=LEFT)
btn13.bind('<Button-1>', lambda e: describe('alcohol'))
btn14 = tk.Button(root, text='quality', width=10, height=3)
btn14.pack(side=LEFT)
btn14.bind('<Button-1>', lambda e: describe('quality'))
#buttons for wine choices
btn1 = tk.Button(root, text = "white", width=10, height=2)
btn1.pack(side=TOP)
#remember which button user picks
btn1.bind('<Button-1>', lambda e: wine_choice('white'))
btn2 = tk.Button(root, text = "red", width=10, height=2)
btn2.pack(side=TOP)
btn2.bind('<Button-1>', lambda e: wine_choice('red'))
#must be called for window to be drawn and events to be processed
root.mainloop()
解决方案是将您的 UI 分成逻辑组,并使用框架来组织逻辑组。您可以让现有的东西发挥作用,但使用框架来组织小部件要容易得多。
我大概看到四个逻辑组:
- 一组两个垂直堆叠的按钮
- 十几个垂直排列的按钮
- 带有“直方图”按钮的统计块
- 直方图
因此,首先创建四个框架,每个部分一个。垂直堆叠最好使用 pack
.
完成后,将各种小部件放入其中一个框架中。从布局角度来看,每个框架都是独立的,因此您可以在每个框架中使用 grid
或 pack
。虽然,由于每个组似乎都是垂直或水平分组,pack
可能在所有情况下都效果最好,因为它在 left-to-right 和 top-to-bottom 布局方面表现出色,代码行最少。