I'm currently halfway through a Python project, but would like a review before I spend too much more time on this to avoid going too far down a rabbit hole.
I had previously wanted to use HTML, CSS, and JavaScript, but I swapped to Python so I can get the current Window's user while opening my app.
At my work, we have labels that look like this:
We print out this paper and put a label on the left-hand side, and then get written sign-off on it from various stakeholders. The labels are for products such as seeds, nuts, beans, etc. The specific design and layout of the label will vary based on our customer.
Current, paper workflow:
- The originator creates the form and hands it to the managers who need to sign off
- The managers initial (the two rightmost columns) to show that they have signed off. Sometimes only person needs to sign off, sometimes two.
- Once everything is done, someone will sign and date the label to verify that the label is good to go.
With the new Python application, I would like to be able to accomplish the same workflow without ever needing the physical piece of paper being passed around.
Here is my current (but incomplete) code:
from tkinter import *
import glob
import os
from PIL import Image, ImageTk, ImageGrab
import tkinter as tk
import datetime
#date & time
now = datetime.datetime.now()
root = tk.Tk()
root.title("SIGN OFF")
root.minsize(840, 800)
# Add a grid
mainframe = tk.Frame(root)
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
mainframe.pack(pady=100, padx=100)
# Create a Tkinter variable
tkvar = tk.StringVar(root)
# Directory
directory = "C:/Users/eduards/Desktop/work/data/to-do"
choices = glob.glob(os.path.join(directory, "*.jpg"))
tkvar.set('...To Sign Off...') # set the default option
# Dropdown menu
popupMenu = tk.OptionMenu(mainframe, tkvar, *choices)
tk.Label(mainframe, text="Choose your sign off here:").grid(row=1, column=1)
popupMenu.grid(row=2, column=1)
label2 = tk.Label(mainframe, image=None)
label2.grid(row = 4, column = 1, rowspan = 10)
# On change dropdown callback.
def change_dropdown(*args):
""" Updates label2 image. """
imgpath = tkvar.get()
img = Image.open(imgpath)
img = img.resize((240,250))
photo = ImageTk.PhotoImage(img)
label2.image = photo
label2.configure(image=photo)
tk.Button(mainframe, text="Open", command=change_dropdown).grid(row=3, column=1)
def var_states():
text_file = open("logfile.txt", "a")
text_file.write("TIME: %s, USER: %s, One %d, Two %d\n" % (now,os.getlogin(), var1.get(), var2.get()))
text_file.close()
print("One %d, Two %d" % (var1.get(), var2.get()))
var1 = IntVar()
Checkbutton(mainframe, text="Ingredients present in full (any allergens in bold with allergen warning if necessary)", variable=var1).grid(column = 2, row=1, sticky=W)
var2 = IntVar()
Checkbutton(mainframe, text="May Contain Statement.", variable=var2).grid(column = 2, row=2, sticky=W)
var3 = IntVar()
Checkbutton(mainframe, text="Cocoa Content (%).", variable=var3).grid(column = 2, row=3, sticky=W)
var4 = IntVar()
Checkbutton(mainframe, text="Vegetable fat in addition to Cocoa butter", variable=var4).grid(column = 2, row=4, sticky=W)
var5 = IntVar()
Checkbutton(mainframe, text="Instructions for Use.", variable=var5).grid(column = 2, row=5, sticky=W)
var6 = IntVar()
Checkbutton(mainframe, text="Additional warning statements (pitt/stone, hyperactivity etc)", variable=var6).grid(column = 2, row=6, sticky=W)
var7 = IntVar()
Checkbutton(mainframe, text="Nutritional Information Visible", variable=var7).grid(column = 2, row=7, sticky=W)
var8 = IntVar()
Checkbutton(mainframe, text="Storage Conditions", variable=var8).grid(column = 2, row=8, sticky=W)
var9 = IntVar()
Checkbutton(mainframe, text="Best Before & Batch Information", variable=var9).grid(column = 2, row=9, sticky=W)
var10 = IntVar()
Checkbutton(mainframe, text="Net Weight & Correct Font Size.", variable=var10).grid(column = 2, row=10, sticky=W)
var11 = IntVar()
Checkbutton(mainframe, text="Barcode - Inner", variable=var11).grid(column = 2, row=11, sticky=W)
var12 = IntVar()
Checkbutton(mainframe, text="Address & contact details correct", variable=var12).grid(column = 2, row=12, sticky=W)
def user():
user_input = os.getlogin()
tk.Label(mainframe, text = user_input, font='Helvetica 18 bold').grid(row = 0, column = 1)
user()
def save():
# pyautogui.press('alt')
# pyautogui.press('printscreen')
# img = ImageGrab.grabclipboard()
# img.save('paste.jpg', 'JPEG')
var_states()
tk.Button(mainframe, text = "Save", command = save).grid(row = 20, column = 1)
root.mainloop()
Here is the output:
The top part in bold (Label
in the sample image) is the current Windows user's username. The dropdown menu below that is the list of JPG files that need signing (TODO: structure the files to only show specific file names that need signing).
When you click "Save", a log file will be generated that shows your timestamped choices (TODO: add code to return which image was touched).
I've also realized that this currently only supports a single person signing, but I will need to restructure to support allowing multiple (currently up to 2) people to sign it.
Below is the file system for labels in JPG. Customer account number which is unique, as an example SFDG001 is one customer and ALPI001 is another. 2nd is the product code, each customer takes different product codes and never will have the same product code. (I know the images look the same, but its for test purposes)
UPDATE 26/09/2019 - NEW CODE
here is my updated code:
from tkinter import *
from tkinter import DISABLED
import tkinter.ttk as ttk
import os
import glob
from PIL import Image, ImageTk, ImageGrab
from pathlib import Path
# from openpyxl import load_workbook
class App():
def __init__(self,master):
notebook = ttk.Notebook(master)
notebook.pack(expand = 1, fill = "both")
#Frames
main = ttk.Frame(notebook)
manual = ttk.Frame(notebook)
notebook.add(main, text='Main-Screen')
notebook.add(manual, text='Manual')
#Check boxes
#Assigning Integers to variables
var1 = IntVar()
var1a = IntVar()
var2 = IntVar()
var2a = IntVar()
var3 = IntVar()
var3a = IntVar()
var4 = IntVar()
var4a = IntVar()
var5 = IntVar()
var5a = IntVar()
var6 = IntVar()
var6a = IntVar()
var7 = IntVar()
var7a = IntVar()
var8 = IntVar()
var8a = IntVar()
var9 = IntVar()
var9a = IntVar()
var10 = IntVar()
var10a = IntVar()
var11 = IntVar()
var11a = IntVar()
var12 = IntVar()
var12a = IntVar()
#Text boxes for initials
#Displaying checkboxes and assigning to variables
self.Checkbox1 = Checkbutton(main, text="Ingredients present in full (any allergens in bold with allergen warning if necessary)", variable=var1)
self.Checkbox1.grid(column = 2, row = 1, sticky = W)
self.Checkbox2 = Checkbutton(main, variable = var1a)
self.Checkbox2.grid(column = 1, row = 1, sticky = W)
self.Checkbox3 = Checkbutton(main, text="May Contain Statement.", variable=var2)
self.Checkbox3.grid(column = 2, row = 2, sticky = W)
self.Checkbox4 = Checkbutton(main, variable = var2a)
self.Checkbox4.grid(column = 1, row = 2, sticky = W)
self.Checkbox5 = Checkbutton(main, text="Cocoa Content (%).", variable=var3)
self.Checkbox5.grid(column = 2, row = 3, sticky = W)
self.Checkbox6 = Checkbutton(main, variable = var3a)
self.Checkbox6.grid(column = 1, row = 3, sticky = W)
self.Checkbox7 = Checkbutton(main, text="Vegetable fat in addition to Cocoa butter", variable=var4)
self.Checkbox7.grid(column = 2, row = 4, sticky = W)
self.Checkbox8 = Checkbutton(main, variable = var4a)
self.Checkbox8.grid(column = 1, row = 4, sticky = W)
self.Checkbox9 = Checkbutton(main, text="Instructions for Use.", variable=var5)
self.Checkbox9.grid(column = 2, row = 5, sticky = W)
self.Checkbox10 = Checkbutton(main, variable = var5a)
self.Checkbox10.grid(column = 1, row = 5, sticky = W)
self.Checkbox11 = Checkbutton(main, text="Additional warning statements (pitt/stone, hyperactivity etc)", variable=var6)
self.Checkbox11.grid(column = 2, row = 6, sticky = W)
self.Checkbox12 = Checkbutton(main, variable = var6a)
self.Checkbox12.grid(column = 1, row = 6, sticky = W)
self.Checkbox13 = Checkbutton(main, text="Nutritional Information Visible", variable=var7)
self.Checkbox13.grid(column = 2, row = 7, sticky = W)
self.Checkbox14 = Checkbutton(main, variable = var7a)
self.Checkbox14.grid(column = 1, row = 7, sticky = W)
self.Checkbox15 = Checkbutton(main, text="Storage Conditions", variable=var8)
self.Checkbox15.grid(column = 2, row = 8, sticky = W)
self.Checkbox16 = Checkbutton(main, variable = var8a)
self.Checkbox16.grid(column = 1, row = 8, sticky = W)
self.Checkbox17 = Checkbutton(main, text="Best Before & Batch Information", variable=var9)
self.Checkbox17.grid(column = 2, row = 9, sticky = W)
self.Checkbox18 = Checkbutton(main, variable = var9a)
self.Checkbox18.grid(column = 1, row = 9, sticky = W)
self.Checkbox19 = Checkbutton(main, text="Net Weight & Correct Font Size.", variable=var10)
self.Checkbox19.grid(column = 2, row = 10, sticky = W)
self.Checkbox20 = Checkbutton(main, variable = var10a)
self.Checkbox20.grid(column = 1, row = 10, sticky = W)
self.Checkbox21 = Checkbutton(main, text="Barcode - Inner", variable=var11)
self.Checkbox21.grid(column = 2, row = 11, sticky = W)
self.Checkbox22 = Checkbutton(main, variable = var11a)
self.Checkbox22.grid(column = 1, row = 11, sticky = W)
self.Checkbox23 = Checkbutton(main, text="Address & contact details correct", variable=var12)
self.Checkbox23.grid(column = 2, row = 12, sticky = W)
self.Checkbox24 = Checkbutton(main, variable = var12a)
self.Checkbox24.grid(column = 1, row = 12, sticky = W)
##DISABLE ON CLICK##
def showstate(*args):
if var1.get() or var2.get() or var3.get() or var4.get() or var5.get() or var6.get() or var7.get() or var8.get() or var9.get() or var10.get() or var11.get() or var12.get():
self.Checkbox2.config(state = DISABLED)
self.Checkbox4.config(state = DISABLED)
self.Checkbox6.config(state = DISABLED)
self.Checkbox8.config(state = DISABLED)
self.Checkbox10.config(state = DISABLED)
self.Checkbox12.config(state = DISABLED)
self.Checkbox14.config(state = DISABLED)
self.Checkbox16.config(state = DISABLED)
self.Checkbox18.config(state = DISABLED)
self.Checkbox20.config(state = DISABLED)
self.Checkbox22.config(state = DISABLED)
self.Checkbox24.config(state = DISABLED)
if var1a.get() or var2a.get() or var3a.get() or var4a.get() or var5a.get() or var6a.get() or var7a.get() or var8a.get() or var9a.get() or var10a.get() or var11a.get() or var12a.get():
self.Checkbox1.config(state = DISABLED)
self.Checkbox3.config(state = DISABLED)
self.Checkbox5.config(state = DISABLED)
self.Checkbox7.config(state = DISABLED)
self.Checkbox9.config(state = DISABLED)
self.Checkbox11.config(state = DISABLED)
self.Checkbox13.config(state = DISABLED)
self.Checkbox15.config(state = DISABLED)
self.Checkbox17.config(state = DISABLED)
self.Checkbox19.config(state = DISABLED)
self.Checkbox21.config(state = DISABLED)
self.Checkbox23.config(state = DISABLED)
var1.trace_variable("w", showstate)
var1a.trace_variable("w", showstate)
var2.trace_variable("w", showstate)
var2a.trace_variable("w", showstate)
var3.trace_variable("w", showstate)
var3a.trace_variable("w", showstate)
var4.trace_variable("w", showstate)
var4a.trace_variable("w", showstate)
var5.trace_variable("w", showstate)
var5a.trace_variable("w", showstate)
var6.trace_variable("w", showstate)
var6a.trace_variable("w", showstate)
var7.trace_variable("w", showstate)
var7a.trace_variable("w", showstate)
var8.trace_variable("w", showstate)
var8a.trace_variable("w", showstate)
var9.trace_variable("w", showstate)
var9a.trace_variable("w", showstate)
var10.trace_variable("w", showstate)
var10a.trace_variable("w", showstate)
var11.trace_variable("w", showstate)
var11a.trace_variable("w", showstate)
var12.trace_variable("w", showstate)
var12a.trace_variable("w", showstate)
##DISABLE ON CLICK##
#Send data
def var_states():
text_file = open("logfile.txt", "a")
text_file.write("USER: %s, One %d\n" % (os.getlogin(), var1.get()))
text_file.close()
self.dataSend = Button(main, text = "Send", command = var_states).grid(column = 1, row = 13, sticky = W)
###################################################################################################################################
##Load Image##
###################################################################################################################################
# Create a Tkinter variable
tkvar = StringVar(root)
# Directory
directory = "//SERVER/shared_data/Technical/Label Sign Off Sheets/sign off project"
choices = glob.glob(os.path.join(directory, "*- to sign.jpg"))
tkvar.set('...To Sign Off...') # set the default option
# Images
def change_dropdown():
imgpath = tkvar.get()
img = Image.open(imgpath)
img = img.resize((529,361))
photo = ImageTk.PhotoImage(img)
label2.image = photo
label2.configure(image=photo)
#return path value
p = None
def func(value):
global p
p = Path(value)
print('req:', p)
#widgets
self.msg1 = Label(main, text = "Choose here")
self.msg1.grid(column = 0, row = 0)
self.popupMenu = OptionMenu(main, tkvar, *choices)
self.popupMenu.grid(row=1, column=0)
self.display_label = label2 = Label(main, image=None)
self.display_label.grid(row=2, column=0, rowspan = 500)
self.open_button = Button(main, text="Open", command=change_dropdown)
self.open_button.grid(row=502, column=0)
###################################################################################################################################
##Tab 2 - Manual##
###################################################################################################################################
def open_doc():
os.system("start C:/Users/Eduards/Desktop/Portfolio")
self.Manual_Button = Button(manual, text = "Open Manual", command = open_doc)
self.Manual_Button.pack()
root = Tk()
root.minsize(950, 450)
root.title("SIGN OFF LABELS")
app = App(root)
root.mainloop()
Have added another checkboxes, if one side is clicked, the other side is disabled.
Added tabs, need to work on manual, to open a docx file.
Next, I will concentrate on adding a log in window for users to log in.