0

I'm building a GUI to write to an excel spreadsheet. However, before I do the writing to spreadsheet, the user will input data in the GUI. What I want to do is when the user puts in a release number in the first entry and "tab" to the next entry, I want the date to automatically populate.

import tkinter
from tkinter import ttk
from tkinter import messagebox
import os
import openpyxl
from datetime import datetime


window = tkinter.Tk()
window.title("Truck Log Entry Form")

frame = tkinter.Frame(window)
frame.pack()

#saving truck logs
truck_info_frame = tkinter.LabelFrame(frame, text="Truck Information")
truck_info_frame.grid(row= 0, column=0, padx=20, pady=10)

release_number_label = tkinter.Label(truck_info_frame, text="Release Number")
release_number_label.grid(row=0,column=0)
truck_name_label = tkinter.Label(truck_info_frame, text="Truck Name")
truck_name_label.grid(row=0, column=1)
tare_info_label = tkinter.Label(truck_info_frame, text="Tare Weight")
tare_info_label.grid(row=0, column=2)
date_info_label = tkinter.Label(truck_info_frame, text="Date/Time")
date_info_label.grid(row=0, column=3)
gross_info_label = tkinter.Label(truck_info_frame, text = "Gross Weight")
gross_info_label.grid(row=0, column=4)


date_info_result_str = tkinter.StringVar()

release_number_entry = tkinter.Entry(truck_info_frame, textvariable=date_info_result_str)
truck_name_entry = tkinter.Entry(truck_info_frame)
tare_info_entry = tkinter.Entry(truck_info_frame)
#date_info_result = tkinter.Label(truck_info_frame, text='')
date_info_result = tkinter.Label(truck_info_frame)
date_info_result.grid(row=1, column=3)
date_info_result_str.trace('w', lambda *args: auto_date(release_number_entry.get()) )
release_number_entry.grid(row=1, column=0)
truck_name_entry.grid(row=1, column=1)
tare_info_entry.grid(row=1, column=2)


for widget in truck_info_frame.winfo_children():
    widget.grid_configure(padx=10, pady=5)

def auto_date(release_filled):

    print("in auto_date function " + release_filled)
    #release_filled = release_number_entry.get()

    if len(release_filled) >= 6:
        print("in len area")
        #datetime object containing current date and time
        now = datetime.now()

        #format date and time to dd/mm/YY H:M:S
        dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
        return dt_string
    else:
        print("made in error")
        #tkinter.messagebox.showwarning(title="Error", message="Please check release number")

window.mainloop()


I created a function for it to be called then tried to do a .trace method but that doesn't seem to work. Furthermore, I tried messing around with validate but it only returns true or false and I'm not sure how to get that and I suppose call another function to display the time under the data_info_label. I would appreciate any help on this.

Update (1/12/23): I was able to call on the function and get it to trace successfully but how do I return the date and time from the function into the label?

CptLuna
  • 45
  • 5
  • 1
    There are 2 problems with `.trace('1', auto_date(...) )`. First of all, the first parameter of `.trace` should be `"w"`. Second, it should be `lambda: auto_date(...)` instead of just `auto_date(...)` - look [here](https://stackoverflow.com/q/6920302/11106801) for more info. – TheLizzard Jan 12 '23 at 14:58
  • So I modified it to what you suggested but now it's not even calling on the function anymore and I looked at the link you gave me. This is for a button and I do not want a button as a cause-and-effect but rather when I tab out of the entry box to go to the next entry box. However, this is a good start but for some reason, it's not calling on the function after I tab out. – CptLuna Jan 12 '23 at 15:22
  • The question I linked had the same problem, when `tkinter` expects a function, you can't call the function beforehand. In both cases, instead of `auto_date(...)` you need `lambda: auto_date(...)`. Also `date_info_result_str` isn't linked to anything. Please look at some `tkinter` tutorials. – TheLizzard Jan 12 '23 at 15:25
  • I'm not trying to call it beforehand. I'm trying to call it after the "Release Number" box is filled so I can auto-populate the date/time label. – CptLuna Jan 12 '23 at 15:35

2 Answers2

0

What I want to do is when the user puts in a release number in the first entry and "tab" to the next entry, I want the date to automatically populate.

If you want to do something when the user presses the tab key, you can bind a function to the event <Tab>. You don't want to do it on a trace associated with a stringvar since that would be called every time the user inserts or deletes a single character.

Here's a very simple example showing one way to do it:

import tkinter as tk
from datetime import datetime

def insert_date(entry):
    now = datetime.now()
    label.configure(text=now.strftime("%c"))

root = tk.Tk()

entry = tk.Entry(root)
label = tk.Label(root)
entry.pack(side="top")
label.pack(side="top")

entry.bind("<Tab>", lambda event: insert_date(label))

root.mainloop()

When you run the above example and press the tab key while the first entry has keyboard focus, it will insert the date and time into the second entry.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • This helps a ton!! Now, if I don't want to modify an entry box, could I use .setvar to modify the label (date_info_result) with the date/time result? – CptLuna Jan 12 '23 at 17:13
  • @CptLuna: you can do anything you want in the callback. I apologize for not reading the question closely enough. I've updated the example to modify a label rather than insert the data into an entry. – Bryan Oakley Jan 12 '23 at 17:13
  • oh no problem, I didn't see your response but figured it out by using the configue but you definitely did it differently than I did. Thank you, thank you! – CptLuna Jan 12 '23 at 17:23
0

Thanks to @Brian Oakley, I was able to figure out the rest! Huge help and here's the code below to see how I did it.

import tkinter
from tkinter import ttk
from tkinter import messagebox
import os
import openpyxl
from datetime import datetime


window = tkinter.Tk()
window.title("Truck Log Entry Form")

frame = tkinter.Frame(window)
frame.pack()

#saving truck logs
truck_info_frame = tkinter.LabelFrame(frame, text="Truck Information")
truck_info_frame.grid(row= 0, column=0, padx=20, pady=10)

release_number_label = tkinter.Label(truck_info_frame, text="Release Number")
release_number_label.grid(row=0,column=0)
truck_name_label = tkinter.Label(truck_info_frame, text="Truck Name")
truck_name_label.grid(row=0, column=1)
tare_info_label = tkinter.Label(truck_info_frame, text="Tare Weight")
tare_info_label.grid(row=0, column=2)
date_info_label = tkinter.Label(truck_info_frame, text="Date/Time")
date_info_label.grid(row=0, column=3)
gross_info_label = tkinter.Label(truck_info_frame, text = "Gross Weight")
gross_info_label.grid(row=0, column=4)


#date_info_result_str = tkinter.StringVar()

#release_number_entry = tkinter.Entry(truck_info_frame, textvariable=date_info_result_str)
release_number_entry = tkinter.Entry(truck_info_frame)
truck_name_entry = tkinter.Entry(truck_info_frame)
tare_info_entry = tkinter.Entry(truck_info_frame)
#date_info_result = tkinter.Label(truck_info_frame, text='')
date_info_result = tkinter.Label(truck_info_frame)
date_info_result.grid(row=1, column=3)
#date_info_result_str.trace('w', lambda *args: auto_date(release_number_entry.get()) )
release_number_entry.grid(row=1, column=0)
truck_name_entry.grid(row=1, column=1)
tare_info_entry.grid(row=1, column=2)

release_number_entry.bind("<Tab>", lambda event: auto_date(release_number_entry.get()))


for widget in truck_info_frame.winfo_children():
    widget.grid_configure(padx=10, pady=5)

def auto_date(release_filled):

    print("in auto_date function " + release_filled)
    #release_filled = release_number_entry.get()

    if len(release_filled) >= 6:
        print("in len area")
        #datetime object containing current date and time
        now = datetime.now()

        #format date and time to dd/mm/YY H:M:S
        dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
        date_info_result.config(text = dt_string)
    else:
        print("made in error")
        #tkinter.messagebox.showwarning(title="Error", message="Please check release number")

window.mainloop()
CptLuna
  • 45
  • 5