guyd
guyd

Reputation: 733

Tkinter GUI – How to remove a row of Entry widgets, using a Button

I am building a table, using ttk.Entry and `ttk.Combobox' ( rows and columns – amount of rows can vary).

User should be able to delete an entire row of that table using a “Delete Button” placed on GUI.

  1. Line to be deleted can be placed anywhere ( first, last, anywhere in between).
  2. Without adding “checkbox” widget at the end/beginning of each line to flag the desired line.

Tried:

a) Using focus_get() to determine Entry’s row number, and then to delete entire row of widgets. But, when pressing “Delete Button” focus_get() changes from Entry’s to Button’s and “Delete Button” got deleted.

b) I haven't tried, but there is a way using class bind to entire, but it seems not elegant.

Any ideas what is the “right” way to so that?

Edit 1: Adding pic of GUI. Selecting any Entry, would delete entire row of widgets

Upvotes: 0

Views: 5125

Answers (2)

guyd
guyd

Reputation: 733

As @Bryan Oakley suggested, here is the relevant portion of updated code- as an answer to my question.

Button's focus was set to False

del_row_button = ttk.Button(buttons_frame, width=10, text="Delete Row", takefocus=False, command=self.del_row)
        del_row_button.grid(row=1, column=1, pady=5, padx= 5)

and self.del_row_button callback updated to delete the exact line in self.datafile by getting widget's row number using grid_info().get('row')-1

def del_row(self):

        #delete data from list
        del self.datafile[self.class_frame.focus_get().grid_info().get('row') -1]

        #save data
        self.save_data()

        #destroy and rebuild rows with updated data
        self.rows_frame.destroy()
        self.rebuild_table()

        print("row deleted")

Upvotes: 0

Bryan Oakley
Bryan Oakley

Reputation: 385970

You don't state it in your question, but I'm assuming you're using ttk for the buttons. The ttk button widget takes focus when you click on it, which is both different from tkinter, and different from how buttons should work in general. In my opinion this is a bug in the ttk button, but I raised the issue years ago and the developers decided to keep the behavior.

The quick fix is to set the takefocus option to False for the button. This has the unfortunately side effect of breaking the ability to traverse your gui with the keyboard (eg: press tab to give move focus from widget to widget). Both problems can be solved with some custom bindings.

Here is a program that illustrates the difference between setting takefocus to False and True

import tkinter as tk
from tkinter import ttk

root = tk.Tk()

def click():
    label.configure(text="Widget with focus: %s" % root.focus_get())

e1 = ttk.Entry(root, name="e1")
e2 = ttk.Entry(root, name="e2")
label = ttk.Label(root)

b1 = ttk.Button(root, text="Steal focus", command=click, name="b1", takefocus=True)
b2 = ttk.Button(root, text="Don't Steal focus", command=click, name="b2", takefocus=False)

e1.pack(fill="x")
e2.pack(fill="x")
label.pack(side="top", fill="both", expand=True)
b1.pack(side="left")
b2.pack(side="left")

root.mainloop()

Upvotes: 2

Related Questions