强制TKinter按钮输出到窗口底部?

问题描述

我对使用TKinter非常陌生。我正在制作一个TKinter窗口,该窗口显示wine quality data sets的描述性统计信息。我的问题是定位。即使使用pack(side=BottOM),直方图的按钮也会显示在我拥有的列选项按钮旁边,如下所示:

enter image description here

理想情况下,我希望窗口看起来像这样:

enter image description here

我尝试将按钮制作在与“描述性统计信息”标签相同的位置,然后稍后对其进行配置,但是虽然此按钮将按钮保持在我希望的位置,但直方图最终位于同一位置。

编辑:我本来是使用grid()手动放置所有内容的,但是出于审美原因,我不喜欢随着更多对象的出现,按钮之间的间距如何调整添加到窗口。即使我将所有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',height=3)
    btn3.pack(side=LEFT)
    btn3.bind('<Button-1>',lambda e: describe('fixed acidity'))

    btn4 = tk.Button(root,text='volatile\nacidity',height=3)
    btn4.pack(side=LEFT)
    btn4.bind('<Button-1>',lambda e: describe('volatile acidity'))

    btn5 = tk.Button(root,text='citric\nacid',height=3)
    btn5.pack(side=LEFT)
    btn5.bind('<Button-1>',lambda e: describe('citric acid'))

    btn6 = tk.Button(root,text='residual\nsugar',height=3)
    btn6.pack(side=LEFT)
    btn6.bind('<Button-1>',lambda e: describe('residual sugar'))

    btn7 = tk.Button(root,text='chlorides',height=3)
    btn7.pack(side=LEFT)
    btn7.bind('<Button-1>',lambda e: describe('chlorides'))

    btn8 = tk.Button(root,text='free\nsulfur\ndioxide',height=3)
    btn8.pack(side=LEFT)
    btn8.bind('<Button-1>',lambda e: describe('free sulfur dioxide'))

    btn9 = tk.Button(root,text='total\nsulfur\ndioxide',height=3)
    btn9.pack(side=LEFT)
    btn9.bind('<Button-1>',lambda e: describe('total sulfur dioxide'))

    btn10 = tk.Button(root,text='density',height=3)
    btn10.pack(side=LEFT)
    btn10.bind('<Button-1>',lambda e: describe('density'))

    btn11 = tk.Button(root,text='pH',height=3)
    btn11.pack(side=LEFT)
    btn11.bind('<Button-1>',lambda e: describe('pH'))

    btn12 = tk.Button(root,text='sulphates',height=3)
    btn12.pack(side=LEFT)
    btn12.bind('<Button-1>',lambda e: describe('sulphates'))

    btn13 = tk.Button(root,text='alcohol',height=3)
    btn13.pack(side=LEFT)
    btn13.bind('<Button-1>',lambda e: describe('alcohol'))

    btn14 = tk.Button(root,text='quality',height=3)
    btn14.pack(side=LEFT)
    btn14.bind('<Button-1>',lambda e: describe('quality'))

#buttons for wine choices
btn1 = tk.Button(root,text = "white",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",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进行垂直堆叠。

完成此操作后,请将各种小部件放入其中一个框架中。每个框架从布局角度来看都是独立的,因此您可以在每个框架中使用gridpack。但是,由于每个组似乎都是垂直或水平分组,因此pack在所有情况下都可能效果最好,因为它擅长于从左到右和从上到下的布局,并且代码行最少。 / p>