Tkinter Quick Form Script


I've been playing around with Tkinter this week. What is Tkinter? Tkinter allows you to build GUI based applications in Python. It's not the only GUI library for Python, but it is included when you install Python. So pretty much any install of Python is going to include Tkinter. I just repeated myself didn't I? Oh well. So why build GUI based applications. Well for ease of use. Most end-users today, would laugh if you gave them a console application. Despite the fact console applications can often be more efficient than GUI based ones. But at the end of the day, GUI applications just look and feel better.

After playing around with Tkinter, I found I was impressed with how simple it was to get a basic form going. It was so simple, that it was fun. Doing the same in .NET forms would have taken a bit more time. Honestly, unless you need a lot of bells and whistles, Tkinter just works. There have been many times where I needed a simple forms application to make doing certain tasks easier. For example data collection. But sometimes we just don't have time to build tools. This is where I think Tkinter could come in. I thought, what if I made myself a template for data collection. So I did and I'm happy to share it with you.

I present to you, "Quick Form." It's very simple to edit. It doesn't validate what you input, but if you need something quick and dirty to collect some data. This will do the trick! All you need to do is edit the following script, change or add the field names and Bob's your uncle. You can even edit the call back function to do whatever you need. It will pass the data from the form to your call back function. The call back I wrote in the example below creates or appends a CSV file with the data entered in the form. After clicking submit, the call back is called, the form is cleared and the focus is returned to the first field. You can enter hundreds of entries without ever touching your mouse. Now that's what I call efficiency.

This script is free for your use. Just has always, we're not responsible for possible damages. Till next time, happy programing!

import tkinter as tk
import os, csv

class formField:
    def __init__(self, name, description):
        self.name = name
        self.description = description

class form:
    def __init__(self, title, formFields, callback):
        self.title = title
        self.formFields = formFields
        self.callback = callback

        self.window = tk.Tk()

        self.window.title("Quick Form")
        self.window.columnconfigure(1, minsize=250)

        self.fields = []

        for idx, formField in enumerate(self.formFields):
            label = tk.Label(master=self.window, text=formField.description)
            label.grid(row=idx, column=0, padx=5, pady=5, sticky="w")

            entry = tk.Entry(master=self.window)
            entry.grid(row=idx, column=1, padx=5, pady=5, sticky="we")
            
            self.fields.append(entry)

        self.lblMessages = tk.Label(master=self.window, text="")
        self.lblMessages.grid(row=len(self.fields), column=0, columnspan=2, padx=5, pady=5)

        self.btnSubmit = tk.Button(master=self.window, text="Submit")
        self.btnSubmit.grid(row=len(self.fields)+1, column=0, columnspan=2, padx=5, pady=5)
        self.btnSubmit.bind("", self.submit)

        self.fields[0].focus()

        # clear messages when new data is entered
        self.window.bind('', self.clearMessages)

        self.window.mainloop()

    def clearMessages(self, event):
        self.lblMessages.config(text="")

    def submit(self, event):
        self.lblMessages.config(text="")

        values = self.getFieldValues()

        message = self.callback(values)
        self.lblMessages.config(text=message)

        self.clearForm()
        self.fields[0].focus()

    # returns an dictionary of form field values, keyed by field name
    def getFieldValues(self):
        values = {}

        for idx, field in enumerate(self.fields):
            values[self.formFields[idx].name] = field.get()

        return values
    
    def clearForm(self):
        for idx, field in enumerate(self.fields):
            field.delete(0, len(field.get()))
        

def callback(values):
    filename = "output.csv"

    # does the file exist?
    exists = os.path.exists(filename)

    try:
        with open(filename, "a" if exists else "w") as csvfile:
                writer = csv.DictWriter(csvfile, fieldnames=list(values.keys()), lineterminator="\n")
                if not exists: writer.writeheader()
                writer.writerow(values)
        return "Wrote 1 Line"
    except IOError:
        return "I/O error"

formFields = []

formFields.append(formField(name="field1", description="Field 1"))
formFields.append(formField(name="field2", description="Field 2"))
formFields.append(formField(name="field3", description="Field 3"))
formFields.append(formField(name="field4", description="Field 4"))
formFields.append(formField(name="field5", description="Field 5"))
formFields.append(formField(name="field6", description="Field 6"))

form = form(title="Quick Form", formFields=formFields, callback=callback)
  0

Categories: Programming

Tags: python