简体   繁体   中英

make tkinter window shrink, as widgets are deleted

I'm making some program, where I input a bunch of stuff into an entry and it gets printed into a row. I also added a feature where you can delete a row. However, when I delete a row, the window does not shrink. The way I actually made the program was by having 2 frames; the main frame with the buttons and entries, and the output or text frame. When I delete a row, it actually appends the data from a list, deletes the frame and all the widgets and reprints the rows, but with out the row I deleted.

The issue with my code, is that when I delete a row, the rows that weren't deleted start to get smaller and compress and secondly, the bottom of the window doesn't move upwards, leaving a blank white space.

Any help would be appreciated, thanks.

actually appending, labelling and printing the row is in function append_entry() and my delete function is 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()

Under the code


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

add this block of code

        second_frame.pack()

it will be like this


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

I hope this helps you

You can use main_window.geometry("1200x800+100+100") to change size and position of main_window . Here the window width will be 1200 and height will be 800, positioned 100px to the top left corner of screen. The +100+100 is optional.

You may add geometry() to delete_row callback to resize the frame. Though you might have to calculate the proper size after widget deletion.

As to "when I delete a row, the rows that weren't deleted start to get smaller and compress",

That's due to how grid layout works. If there are two widgets on the same grid row, the grid height will be equal the the higher widget height. When the higher widget is removed, the grid will resize to the smaller widget height and appear to 'shrink'.

To solve that, you can try add padding to the widget, the syntax is

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

Alternatively, you may try other layout management: .place will give you absolute layout control. Or you can use pack and let tkinter decide the proper position.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM