【问题标题】:Forcing TKinter button output to bottom of window?强制 TKinter 按钮输出到窗口底部?
【发布时间】:2021-02-11 05:24:27
【问题描述】:

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

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

我尝试在我制作标签“描述性统计”的同一个地方制作按钮,然后稍后配置它,但是虽然这会使按钮保持在我想要的位置,但直方图最终会出现在同一个地方。

编辑:我最初使用grid() 手动放置所有内容,但出于美学原因,我不喜欢按钮之间的空间如何随着添加更多对象而调整窗户。即使我已将所有pack()s 更改为grid()s,我也收到“无法使用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()

【问题讨论】:

  • 尝试使用.place(x, y),但它不适用于扩展窗口其他选项是使用.grid(row, column)并将所有内容放在网格中,但要小心
  • 是的,我遇到了.grid() 的一些问题。我会调查.place(x,y)!感谢您提及。

标签: python-3.x matplotlib tkinter canvas tk


【解决方案1】:

解决方案是将您的 UI 分解为逻辑组,并使用框架来组织逻辑组。你可以让你拥有的东西发挥作用,但使用框架来组织你的小部件要容易得多。

我可能看到四个逻辑组:

  • 一组垂直堆叠的两个按钮
  • 十几个垂直排列的按钮
  • 带有“直方图”按钮的统计数据块
  • 直方图

因此,首先创建四个框架,每个部分一个。垂直堆叠最好使用pack

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

【讨论】:

  • 有趣!我会看看它是如何实现四个帧的。非常感谢您的建议。
  • 这最终工作得非常漂亮。非常感谢tk.Frame() 引起我的注意。我最终使用了 3 帧。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-02
  • 1970-01-01
  • 1970-01-01
  • 2016-10-23
  • 2013-11-19
相关资源
最近更新 更多