【问题标题】:make tkinter window shrink, as widgets are deleted使 tkinter 窗口缩小,因为小部件被删除
【发布时间】:2020-08-28 14:35:51
【问题描述】:

我正在制作一些程序,在其中我将一堆东西输入到一个条目中,然后将其打印成一行。我还添加了一个可以删除行的功能。但是,当我删除一行时,窗口不会缩小。我实际制作程序的方式是有 2 帧;带有按钮和条目的主框架,以及输出或文本框架。当我删除一行时,它实际上是从列表中追加数据,删除框架和所有小部件并重新打印行,但没有我删除的行。

我的代码的问题是,当我删除一行时,未删除的行开始变小并压缩,其次,窗口底部不会向上移动,留下空白区域。

任何帮助将不胜感激,谢谢。

实际上附加、标记和打印行在函数 append_entry() 中,我的删除函数是 delete_row()

from tkinter import *


global main_window

def quit():
    main_window.destroy()


def entry_labels():
    leader_label = Label(main_frame, text = 'Customer Name')
    leader_label.grid(column=0, row=0)

    location_label = Label(main_frame, text = 'Receipt Number')
    location_label.grid(column=0, row=1)

    numcampers_label = Label(main_frame, text = 'Item Hired')
    numcampers_label.grid(column=0, row=2)

    weather_label = Label(main_frame, text = 'Number Hired')
    weather_label.grid(column=0, row=3)


    row_label = Label(main_frame, text= 'Row')
    row_label.grid(column=3, row=2)

def button():
    print_button = Button(main_frame, text = "Print Details", command = append_entry)
    print_button.grid(column=3, row=1)

    quit_button = Button(main_frame, text= "Quit", command=quit)
    quit_button.grid(column=4, row=0)

    delete_row_button = Button(main_frame, text = 'Delete Row', command = delete_row)
    delete_row_button.grid(column=4, row=3)
    


def entry():
    global name_entry
    name_entry = Entry(main_frame)
    name_entry.grid(column=1, row=0)

    global receipt_entry
    receipt_entry = Entry(main_frame)
    receipt_entry.grid(column=1, row=1)

    global hired_entry
    hired_entry = Entry(main_frame)
    hired_entry.grid(column=1, row=2)

    
    global num_hired_entry
    num_hired_entry = Entry(main_frame)
    num_hired_entry.grid(column=1, row=3)

    global delete_row_entry
    delete_row_entry = Entry(main_frame)
    delete_row_entry.grid(column=4, row=2)

def table_headers():
    row_header = Label(main_frame, text='Row', font = 'Arial 10 bold')
    row_header.grid(column=0, row=4)
    
    customer_header = Label(main_frame, text='Customer Name', font = 'Arial 10 bold')
    customer_header.grid(column=1, row=4)

    receipt_header = Label(main_frame, text='Receipt Number', font = 'Arial 10 bold')
    receipt_header.grid(column=3, row=4)

    item_header = Label(main_frame, text='Item Hired', font = 'Arial 10 bold')
    item_header.grid(column=2, row=4)

    num_header = Label(main_frame, text='Number Hired', font = 'Arial 10 bold')
    num_header.grid(column=4, row=4)

def append_entry():

    
    global second_frame
    second_frame = Frame(main_window)
    second_frame.grid(column=0, row=6)

    leader_error_var.set("")
    location_error_var.set("")
    numcamper_error_var.set("")
    weather_error_var.set("")


    global name_count
    name_count = 0
    global ROWS_ABOVE
    ROWS_ABOVE = 6


    try:
        name_entry_str = str(name_entry.get())
        hired_entry_str = str(hired_entry.get())
        receipt_entry_int = str(receipt_entry.get())
        num_hired_entry_int = str(num_hired_entry.get())



        if len(name_entry.get()) != 0:
            input_data_col1.append([name_entry_str])
            input_data_col2.append([hired_entry_str])
            input_data_col3.append([receipt_entry_int])
            input_data_col4.append([num_hired_entry_int])
            counters['total_entries'] += 1
      

        
        print(input_data_col1)
        print(input_data_col2)
        print(input_data_col3)
        print(input_data_col4)
        
       
        while name_count < counters ['total_entries']:
            global name

            name = Label(second_frame, text=(input_data_col1[name_count][-1]))  ##using -1 selects the latest entry in the list
            name.grid(column=1, row=name_count + ROWS_ABOVE, padx=50)
            
            item = Label(second_frame, text=(input_data_col2[name_count][-1]))
            item.grid(column=2, row=name_count + ROWS_ABOVE, padx=50)
            
            row = Label(second_frame, text=name_count)
            row.grid(column=0, row=name_count + ROWS_ABOVE, padx=60)
            
            receipt = Label(second_frame, text=(input_data_col3[name_count][-1]))
            receipt.grid(column=3, row=name_count + ROWS_ABOVE, padx=50)
            
            num = Label(second_frame, text=(input_data_col4[name_count][-1]))
            num.grid(column=4, row= name_count + ROWS_ABOVE, padx=50)
            
            name_count += 1

        name_entry.delete(0,END)
        receipt_entry.delete(0,END)
        hired_entry.delete(0,END)
        num_hired_entry.delete(0,END)

    except:
        leader_error_var.set("Check inputs")
        #location_error_var.set("please enter a valid num")
        #numcamper_error_var.set("numcamper error test")
        weather_error_var.set("")

        name_entry.delete(0,END)
        receipt_entry.delete(0,END)
        hired_entry.delete(0,END)
        num_hired_entry.delete(0,END)



def delete_row():

    user_del =int(delete_row_entry.get())
     
    counters['total_entries'] -= 1
    input_data_col1.pop(user_del)
    input_data_col2.pop(user_del)
    input_data_col3.pop(user_del)
    input_data_col4.pop(user_del)


    data = [input_data_col1,input_data_col2,input_data_col3,input_data_col4]

    

    for widget in second_frame.winfo_children():
        widget.destroy()

    append_entry()

    
    print(input_data_col1)
    print(input_data_col2)
    print(input_data_col3)
    print(input_data_col4)

     

def error_prevention():
    #leader_error_var.set("leader error test")
    #location_error_var.set("location error test")
    #numcamper_error_var.set("numcamper error test")
    #weather_error_var.set("weather error test")
    #weather_error_var.set("_______________")

    
    leader_error = Label(main_frame, textvariable = leader_error_var, fg = 'red')
    leader_error.grid(column=2, row=0)

    location_error = Label(main_frame, textvariable = location_error_var, fg = 'red')
    location_error.grid(column=2, row=1)

    numcamper_error = Label(main_frame, textvariable = numcamper_error_var, fg = 'red', width = 13)
    numcamper_error.grid(column=2, row=2)
    
    weather_error = Label(main_frame, textvariable = weather_error_var, fg = 'red')
    weather_error.grid(column=2, row=3)


def main():
    global main_window
    main_window = Tk()


    global input_data_col1
    input_data_col1 = []
    
    global input_data_col2
    input_data_col2 = []
    
    global input_data_col3
    input_data_col3 = []
    
    global input_data_col4
    input_data_col4 = []



    global input_data


    input_data = []
    
    global main_frame
    main_frame = Frame(main_window)
    main_frame.grid(row=0,column=0)
    
  
    

    global counters
    counters = {'total_entries':0, 'name_count':0}
    #global number
    #number = {'total_entries':0}

    def stringvars():
        global location_error_var
        location_error_var = StringVar()
        location_error_var.set("")

        global numcamper_error_var
        numcamper_error_var = StringVar()
        numcamper_error_var.set("")

        global leader_error_var
        leader_error_var = StringVar()
        leader_error_var.set("")

        global weather_error_var
        weather_error_var = StringVar()
        leader_error_var.set("")

    stringvars()
    
    entry_labels()
    entry()
    error_prevention()
    button()
    table_headers()


main()
main_window.mainloop()

【问题讨论】:

标签: python list tkinter widget


【解决方案1】:

代码下


    for widget in second_frame.winfo_children():
        widget.destroy()

添加这段代码

        second_frame.pack()

会是这样的


    for widget in second_frame.winfo_children():
        widget.destroy()
        second_frame.pack()

希望对你有帮助

【讨论】:

  • 当我尝试使用条目添加另一行时,它不再扩展。目标是可以伸缩的东西,好像只能删除一行,再删第二行就不动了。
  • 当你删除一行然后添加另一行时你可以再次删除一行你不能同时删除多行我会尝试想出一些东西
【解决方案2】:

你可以使用 main_window.geometry("1200x800+100+100") 更改main_window 的大小和位置。此处窗口宽度为 1200,高度为 800,位于屏幕左上角 100 像素处。 +100+100 是可选的。

您可以将geometry() 添加到delete_row 回调以调整框架大小。虽然您可能必须在小部件删除后计算正确的大小。

至于“当我删除一行时,未删除的行开始变小压缩”,

这是由于网格布局的工作原理。如果同一网格行上有两个小部件,则网格高度将等于较高的小部件高度。当较高的小部件被移除时,网格将调整到较小的小部件高度并显示为“缩小”。

要解决这个问题,你可以尝试给小部件添加填充,语法是

widget.grid(column=1,row=1,padx=(10,10),pady=(10,10))

或者,您可以尝试其他布局管理:.place 会给您绝对的布局控制。或者你可以使用pack 让 tkinter 决定合适的位置。

【讨论】: