0

I know that you can check if the entry box is empty by checking its length. I'm having a hard time implementing it though, because my entry boxes are dynamically created and you can't traverse in all of it in a single loop.

Here is my code:

from tkinter import *

class Window(Canvas):
    def __init__(self,master=None,**kwargs):
        Canvas.__init__(self,master,**kwargs)
        self.frame = Frame(self)
        self.create_window(0,0,anchor=N+W,window=self.frame)
        self.row = 1

        self.input_x = []
        self.input_y = []

        self.x_values = []
        self.y_values = []

        self._init_entries()

    def _init_entries(self):
        x_value  = Label(self.frame, text='x', font='Helvetica 10 bold').grid(row = self.row, column = 2)
        y_value  = Label(self.frame, text='y', font='Helvetica 10 bold').grid(row = self.row, column = 3)
        self.row += 1

    def add_entry(self):

        def validate_int_entry(text):
            if text == "":
                return True
            try:
                value = int(text)
            except ValueError:
                return False
            return value
        vcmd_int = (root.register(validate_int_entry), "%P")

        x_value = Entry(self.frame, validate = "key", validatecommand=vcmd_int, justify = RIGHT, width=10)
        x_value.grid(row = self.row, column = 2)

        y_value = Entry(self.frame, validate = "key", validatecommand=vcmd_int, justify = RIGHT, width=10)         
        y_value.grid(row = self.row, column = 3)

        self.row += 1

        self.input_x.append(x_value)
        self.input_y.append(y_value)


    def save_entry(self):

        self.x_values.clear()
        self.y_values.clear()

        for entry in self.input_x:
            x = int(entry.get())
            self.x_values.append(x)
        print(self.x_values)

        for entry in self.input_y:
            x = int(entry.get())
            self.y_values.append(x)
        print(self.y_values)


if __name__ == "__main__":
    root = Tk()

    root.resizable(0,0)
    root.title('Lot')

    lot = Window(root)
    lot.grid(row=0,column=0)

    scroll = Scrollbar(root)
    scroll.grid(row=0,column=1,sticky=N+S)

    lot.config(yscrollcommand = scroll.set)
    scroll.config(command=lot.yview)
    lot.configure(scrollregion = lot.bbox("all"), width=1000, height=500)

    def add_points():
        lot.add_entry()
        lot.configure(scrollregion = lot.bbox("all"))

    b1 = Button(root, text = "Add points", command = add_points)
    b1.grid(row=1,column=0)

    def get_value():
        b1.destroy()
        lot.save_entry()

    b2 = Button(root, text = "Get value!", command = get_value)
    b2.grid(row=2,column=0)

    root.mainloop()

Here's the GUI example wherein the user clicked the 'Add points' button 5 times but forgot to fill one of the entry boxes.

GUI example Since I set that the entry boxes can only accept 'int', then it will throw an error. How can I show a MessageBox every time an entry box is empty (and if it's possible, can tell the user what entry box is empty)?

aryastark
  • 25
  • 5
  • you can import messagebox from tkinter then show the popup messagebox.showwarning("Warning","Warning message") if field is empty – Sachin Singh Nov 28 '19 at 09:39
  • Yes, I know that. The problem is how I can access the entry boxes since it's been created dynamically. – aryastark Nov 28 '19 at 10:56
  • You store entries in two lists`self.input_x` and `self.input_y`, so loop over the lists and show a warning using item index. – Kenly Nov 28 '19 at 13:50
  • @Kenly, I had a hard time looping in that list since my plan is to put the error handling task inside the 'save_entry' function. Basically, I want the user to fill all the entry boxes first before I do the checking if some of it is empty or not. I managed to do it by using `all(x.get() is not ' ' for x in self.input_x` inside an if-statement and throw an error if returned false. It doesn't look good though with multiple columns. – aryastark Nov 28 '19 at 14:58

1 Answers1

2

I have change your add_entry function before adding new row it will check the both fields if it find it empty the warning message will popup.

def add_entry(self):

    for entry in self.input_x:
        if entry.get() is '':
            return messagebox.showwarning('Warning', 'Empty Fields')

    for entry in self.input_y:
        if entry.get() is '':
            return messagebox.showwarning('Warning', 'Empty Fields')

    def validate_int_entry(text):
        if text == "":
            return True
        try:
            value = int(text)
        except ValueError:
            return False
        return value
    vcmd_int = (root.register(validate_int_entry), "%P")

    x_value = Entry(self.frame, validate = "key", validatecommand=vcmd_int, justify = RIGHT, width=10)
    x_value.grid(row = self.row, column = 2)

    y_value = Entry(self.frame, validate = "key", validatecommand=vcmd_int, justify = RIGHT, width=10)
    y_value.grid(row = self.row, column = 3)

    self.row += 1

    self.input_x.append(x_value)
    self.input_y.append(y_value)
Sachin Singh
  • 607
  • 4
  • 22
  • 1
    That's a nice perspective, checking the (previous) row first before adding another one. Strange as it may seem but it didn't cross my mind. In this case, it will be easy for the user to track the empty box especially with many points. I can also bypass the clearing of the lists, since the 'save_entry' function will only be called after handling the error inside the 'add_entry' function. – aryastark Nov 28 '19 at 15:07
  • @aryastark I'm glad it helped you. – Sachin Singh Nov 29 '19 at 05:06