3
\$\begingroup\$

I had a read about classes, def, self, master, *args, **kwargs, __init__ and roots. Still trying to get my head around the whole thing.

I am struggling to structure my current code into classes and defs.

Here is my current code (below). It works perfectly fine, but I need to re-code it, re-structure it with classes, as I have been given a feedback from @BryanOakley to structure it with classes:

from tkinter import *
from tkinter.ttk import *
import glob
import os
from PIL import Image, ImageTk, ImageGrab
import tkinter as tk
import pyautogui
import datetime
import time
from pathlib import Path

#date & time
now = datetime.datetime.now()

root = tk.Tk()
root.title("SIGN OFF")
root.minsize(840, 400)


root.tk.call('wm', 'iconphoto', root._w, tk.PhotoImage(file='C:/Users/label/Desktop/Sign off project/tick.ico'))

# Frames
left_frame = tk.Frame()
right_frame = tk.Frame()

left_frame.pack(side="left", fill="both", expand=True)
right_frame.pack(side="right", fill="both", expand=True)

# Create a Tkinter variable
tkvar = tk.StringVar(root)

# Directory
directory = "C:/Users/label/Desktop/Sign off Project/sign off img"
choices = glob.glob(os.path.join(directory, "*.jpg"))
tkvar.set('...To Sign Off...') # set the default option

# On change dropdown callback.
def change_dropdown(*args):
    """ Updates label2 image. """
    imgpath = tkvar.get()
    img = Image.open(imgpath)
    img = img.resize((529,361))
    photo = ImageTk.PhotoImage(img)
    label2.image = photo
    label2.configure(image=photo)

p = None

def func(value):
    global p
    p = Path(value)
    print('req:', p)

#Seperating widgets
choose_label = tk.Label(left_frame, text="Choose your sign off here:")
popupMenu = tk.OptionMenu(left_frame, tkvar, *choices,command = func)
display_label = label2 = tk.Label(left_frame, image=None)
open_button = tk.Button(left_frame, text="Open", command=change_dropdown)

choose_label.grid(row=1, column=1)
popupMenu.grid(row=2, column=1)
display_label.grid(row=3, column=1)
open_button.grid(row=4, column=1)







def user():
    tk.Label(right_frame, text= "User: ", font = 'Helvetica 18 bold').grid(column = 1, row = 0, sticky = W)
    user_input = os.getlogin()
    tk.Label(right_frame, text = user_input, font='Helvetica 18 bold').grid(column = 1, row = 0, sticky = N)


user()


def var_states():
    text_file = open("logfile.txt", "a")
    text_file.write("TIME: %s, USER: %s, One %d, Two %d, Three %d, Four %d, Five %d, Six %d, Seven %d, Eight %d, Nine %d, Ten %d, Eleven %d, Twelve %d, Func %s\n" % (now,os.getlogin(), var1.get(), var2.get(), var3.get(), var4.get(), var5.get(), var6.get(), var7.get(), var8.get(), var9.get(), var10.get(), var11.get(), var12.get(), p))
    text_file.close()

#checkboxes
var1 = IntVar()
var2 = IntVar()
var3 = IntVar()
var4 = IntVar()
var5 = IntVar()
var6 = IntVar()
var7 = IntVar()
var8 = IntVar()
var9 = IntVar()
var10 = IntVar()
var11 = IntVar()
var12 = IntVar()

tk.Checkbutton(right_frame, text="Ingredients present in full (any allergens in bold with allergen warning if necessary)", variable=var1).grid(column = 1, row = 1, sticky = W)
tk.Checkbutton(right_frame, text="May Contain Statement.", variable=var2).grid(column = 1, row = 2, sticky = W)
tk.Checkbutton(right_frame, text="Cocoa Content (%).", variable=var3).grid(column = 1, row = 3, sticky = W)
tk.Checkbutton(right_frame, text="Vegetable fat in addition to Cocoa butter", variable=var4).grid(column = 1, row = 4, sticky = W)
tk.Checkbutton(right_frame, text="Instructions for Use.", variable=var5).grid(column = 1, row = 5, sticky = W)
tk.Checkbutton(right_frame, text="Additional warning statements (pitt/stone, hyperactivity etc)", variable=var6).grid(column = 1, row = 5, sticky = W)
tk.Checkbutton(right_frame, text="Nutritional Information Visible", variable=var7).grid(column = 1, row = 7, sticky = W)
tk.Checkbutton(right_frame, text="Storage Conditions", variable=var8).grid(column = 1, row = 8, sticky = W)
tk.Checkbutton(right_frame, text="Best Before & Batch Information", variable=var9).grid(column = 1, row = 9, sticky = W)
tk.Checkbutton(right_frame, text="Net Weight & Correct Font Size.", variable=var10).grid(column = 1, row = 10, sticky = W)
tk.Checkbutton(right_frame, text="Barcode - Inner", variable=var11).grid(column = 1, row = 11, sticky = W)
tk.Checkbutton(right_frame, text="Address & contact details correct", variable=var12).grid(column = 1, row = 12, sticky = W)




def save():

    var_states()


tk.Button(right_frame, text = "Save", command = save).grid(column = 1, row = 13, sticky = W)

root.mainloop()

What needs to be put into classes and what doesn't? I was thinking of having a left_frame and right_frame as two separate classes, or is that not needed?

UPDATE

Here is where I got to.. Am I heading in the right direction?

from tkinter import *
from tkinter import ttk
import glob
import os
from PIL import Image, ImageTk, ImageGrab
import tkinter as tk
import pyautogui
import datetime
import time
from pathlib import Path

class App:
  def __init__(self, master):

     #frames
    left_frame = Frame(master)
    right_frame = Frame(master)

    left_frame.pack(side="left", fill="both", expand=True)
    right_frame.pack(side="right", fill="both", expand=True)

    # Create a Tkinter variable
    App.tkvar = StringVar()

    # Directory
    directory = "C:/Users/label/Desktop/Sign off Project/sign off img"
    choices = glob.glob(os.path.join(directory, "*.jpg"))
    App.tkvar.set('...To Sign Off...') # set the default option

    # On change dropdown callback.
    def change_dropdown(*args):
        """ Updates label2 image. """
        imgpath = App.tkvar.get()
        img = Image.open(imgpath)
        img = img.resize((529,361))
        photo = ImageTk.PhotoImage(img)
        label2.image = photo
        label2.configure(image=photo)


    #Seperating widgets
    self.choose_label = Label(left_frame, text="Choose your sign off here:")
    self.popupMenu = OptionMenu(left_frame, App.tkvar, *choices)
    self.display_label = label2 = Label(left_frame, image=None)
    self.open_button = Button(left_frame, text="Open", command=change_dropdown)

    self.choose_label.grid(row=1, column=1)
    self.popupMenu.grid(row=2, column=1)
    self.display_label.grid(row=3, column=1)
    self.open_button.grid(row=4, column=1)






root = Tk()
root.minsize(840, 400)
app = App(root)
root.mainloop()
\$\endgroup\$
  • \$\begingroup\$ The current question title, which states your concerns about the code, is too general to be useful here. Please edit to the site standard, which is for the title to simply state the task accomplished by the code. Please see How to get the best value out of Code Review: Asking Questions for guidance on writing good question titles. \$\endgroup\$ – BCdotWEB Sep 23 at 14:32
3
\$\begingroup\$

Import sanity

These three:

from tkinter import *
from tkinter.ttk import *
import tkinter as tk

are not all needed at the same time. The first is the messiest - it simply floods your namespace with all tk symbols. The second is similarly messy. You're better off with:

import tkinter as tk
import tkinter.ttk as ttk

Path handling

Especially since you're in Windows, you should rethink your handling of paths. This:

directory = "C:/Users/label/Desktop/Sign off Project/sign off img"
choices = glob.glob(os.path.join(directory, "*.jpg"))

has a few issues. You should probably be using a relative path, first of all. Using an absolute path in a situation like this creates more complicated and fragile code.

Also, consider using the stuff from pathlib to simplify and clean up your filename operations.

My guess is that you'll end up with something like:

from pathlib import Path

choices = Path('sign off img').glob('*.jpg')

Args

def change_dropdown(*args):

The documentation does not mention any args to the callback - so simply delete *args.

Global code

root = Tk()
root.minsize(840, 400)
app = App(root)
root.mainloop()

Put this in a main function:

def main():
    root = Tk()
    root.minsize(840, 400)
    app = App(root)
    root.mainloop()

if __name__ == '__main__':
    main()
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.