Python Forum
Access-Control Tracker - My Tkinter GUI...
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Access-Control Tracker - My Tkinter GUI...
#1
This is the full code thus far of something I am working on right now.
Would love a critique and suggestions for improvements.
Been attempting to learn as I go using only free materials, and I am very new to programming.

Using Python 3.6.7 ([edit] on Ubuntu 18.04):

import tkinter as tk
import tkinter.ttk as ttk
import time


class _Documentation():
    '''
       Separation of functions:

         Functions that work with data input from the GUI will have their own
         class. GUI elements will contain their own logic for GUI operations.

         Entering information by the end-user through the GUI should not be
         manipulated by the GUI classes/elements logic, only checked and sent.

         When an end-user clicks on buttons which modify the GUI,
         _that_logic_ should be contained within the part of the GUI that
         controls its functionality.
    '''
    pass


class LogicHandler(object):
    '''
    _This_ will parse the information that is extracted from the GUI. Such as:
       + When exiting the app; opens a pop-up window to verify choice, closes
         all connections and saves all data.
       + At some point, perhaps provide some kind of logging functions, just
         in case...
       + We use static methods, so they can't indirectly change data. (Correct?)
    '''
    def __init__(self, parent):
        super().__init__
        self.parent = parent
        
    @staticmethod
    def clock_ping():
        return (time.strftime('%H%M'))

    @staticmethod
    def date_ping():
        return time.strftime('%d%b%Y').upper()


class Brass_IO(tk.Tk):
    '''
    Main body of the GUI to which all other objects are attached.
    '''
    def __init__(self): # testing: parent=None
        super().__init__()     # parent
        self.title = self.winfo_toplevel().title( \
            "<=| Access-Control Tracker |=>")

        # top-level item
        self.menu_bar = tk.Menu(self)
        self.config(menu=self.menu_bar)
        self.options_menu = tk.Menu(self.menu_bar, tearoff=0)
        self.menu_bar.add_cascade(label="Options", menu=self.options_menu)
        self.options_menu.add_command(label="Quit", command=self.destroy)

        #
        self.main_frame = tk.Frame(self)
        self.main_frame.grid()

        #
        self.nb = ttk.Notebook(self.main_frame)
        self.nb.grid(padx=(24,0), pady=(24,0), sticky='n,e,s,w')
        self.tab_one = tk.Frame(self.nb)
        self.nb.add(self.tab_one, text='Brass I/O')
        self.tab_two = tk.Frame(self.nb)
        self.nb.add(self.tab_two, text='Edit I/O')
        self.tab_three = tk.Frame(self.nb)
        self.nb.add(self.tab_three, text='Companies')
        self.tab_four = tk.Frame(self.nb)
        self.nb.add(self.tab_four, text='Contractors')
        self.tab_five = tk.Frame(self.nb)
        self.nb.add(self.tab_five, text='Reports')


class TabOne(tk.Frame):
    '''
    Intent:
      This tab will be labeled "Brass I/O". It will contain several widgets,
      which will log #'s in and out by time and date. Below it, a brief
      "history" frame of the last x-number of entries. The back-end to this UI
      element should therefore send the info to a scheduler which puts it all
      into a database. Entry widgets will need to have certain inputs be
      rejected to prevent errors. This helps keep the database intact, and the
      program running as smoothly as possible. Python's logic and branching make
      rejecting the input from the entry label easy, and a popup window can be
      implemented to let the user know what the desired input should be.
      Possibly even a few examples.
      
      Also, a quick listing of statistics in a frame to the right of the
      "entries" section of this tab should yield some useful information to the
      users. A question often asked is, "How many contractors are in right now?"
    '''
    def __init__(self, parent):
        super().__init__(parent)
        self.grid(sticky='n,e,s,w')
        self.parent = parent

        self.tab_one_entries = ttk.LabelFrame(self, text="Entries")
        self.tab_one_entries.grid(column=0, row=0, padx=7,
                             pady=7, ipadx=7, ipady=7)

        ## frame for brass num (entry), brass in & brass out buttons.
        self.tab1_main_top = tk.Frame(self.tab_one_entries)
        self.tab1_main_top.grid(column=0, row=0, sticky="n,e,s,w",
                                padx=5, pady=5, ipadx=6, ipady=6)
        self.tab1_main_top.grid_columnconfigure(0, weight=1)
        # contents
        self.tab1_box = ttk.Entry(self.tab1_main_top, width=10,
                                  justify='center')
        self.tab1_box.grid(column=0, row=0, sticky="n,e,s,w")
        self.tab1_button1 = ttk.Button(self.tab1_main_top, text="Brass In")
        self.tab1_button1.grid(column=1, row=0, sticky="e,w")
        self.tab1_button2 = ttk.Button(self.tab1_main_top, text="Brass Out")
        self.tab1_button2.grid(column=2, row=0, sticky="e,w")

        ## frame for current time
        self.tab1_main_mid = ttk.LabelFrame(self.tab_one_entries,
                                           text="Format: HHMM -------------- \
Enter a time:")
        self.tab1_main_mid.grid(row=1, sticky="e, w", ipadx=6, ipady=6,
                                padx=5, pady=5)
        self.tab1_main_mid.grid_columnconfigure(0, weight=0)
        self.tab1_main_mid.grid_columnconfigure(1, weight=0)
        self.tab1_main_mid.grid_columnconfigure(2, weight=0)
        self.tab1_main_mid.grid_columnconfigure(3, weight=1)

        # contents
        self.timeVar = tk.IntVar()
        self.timeVar.set(1)
        self.tab1_ctime = ttk.Radiobutton(self.tab1_main_mid,
                                          variable=self.timeVar, value=1,
                                          command=self.set_current_time)
        self.tab1_ctime.grid(row=1, column=0, sticky='e')
        self.tab1_ct_label = ttk.Label(self.tab1_main_mid, text="Current Time")
        self.tab1_ct_label.grid(row=1, column=1, padx=(0, 8), sticky="e")
        self.tab1_stime = ttk.Radiobutton(self.tab1_main_mid,
                                          variable=self.timeVar, value=2,
                                          command=self.set_time_entry)
        self.tab1_stime.grid(row=1, column=2, padx=(14, 0), sticky="e")
        self.tab1_stime_entry = ttk.Entry(self.tab1_main_mid, width=10,
                                          justify='center')
        self.tab1_stime_entry.grid(row=1, column=3, padx=(0, 2),
                                   sticky="n,e,s,w")
        self.tab1_stime_entry.grid_remove()
        self.tab1_stime_var = tk.StringVar()
        self.tab1_ct_label = tk.Label(self.tab1_main_mid,
                                      textvariable=self.tab1_stime_var,
                                      justify='center')
        self.tab1_ct_label.grid(row=1, column=3, padx=(0, 2),
                                       sticky="w,e")

        ## frame for current date
        self.tab1_main_bot = ttk.LabelFrame(self.tab_one_entries,
                                           text="Format: DDMONYYYY ----- \
Enter a date:")
        self.tab1_main_bot.grid(row=2, sticky="n,e,s,w",
                                ipadx=6, ipady=6, padx=5, pady=5)
        self.tab1_main_bot.grid_columnconfigure(0, weight=0)
        self.tab1_main_bot.grid_columnconfigure(1, weight=0)
        self.tab1_main_bot.grid_columnconfigure(2, weight=0)
        self.tab1_main_bot.grid_columnconfigure(3, weight=1)

        # contents
        self.dateVar = tk.IntVar()
        self.dateVar.set(1)
        self.tab1_cdate = ttk.Radiobutton(self.tab1_main_bot,
                                          variable=self.dateVar, value=1,
                                          command=self.set_current_date)
        self.tab1_cdate.grid(row=2, sticky="e")
        self.tab1_cd_label = ttk.Label(self.tab1_main_bot, text="Current Date")
        self.tab1_cd_label.grid(row=2, column=1, padx=(0, 8), sticky="e")
        self.tab1_sdate = ttk.Radiobutton(self.tab1_main_bot,
                                          variable=self.dateVar, value=2,
                                          command=self.set_date_entry)
        self.tab1_sdate.grid(row=2, column=2, padx=(14, 0), sticky='e')
        self.tab1_sdate_entry = ttk.Entry(self.tab1_main_bot, width=10,
                                          justify='center')
        self.tab1_sdate_entry.grid(row=2, column=3, padx=(0, 2),
                                   sticky='n,e,s,w')
        self.tab1_sdate_entry.grid_remove()
        self.tab1_sdate_var = tk.StringVar()
        self.tab1_sdate_label = tk.Label(self.tab1_main_bot,
                                         textvariable=self.tab1_sdate_var,
                                         justify='center')
        self.tab1_sdate_label.grid(row=2, column=3, padx=(0, 2), sticky='w,e')

        ## Quick View frame (top right) of Tab 1
        self.tab1_qv = ttk.LabelFrame(self, text="Quick View")
        self.tab1_qv.grid(column=1, row=0, sticky='n,e,s,w',
                           padx=7, pady=7, ipadx=7, ipady=7)
        
        # contents
        self.tab1_qv_label = tk.Label(self.tab1_qv,
                                      text="Number of people in right now...\n\
Do tk labels display multi lines?\n\
Yes they do!\n\
But they look like poop in the code lol.")
        self.tab1_qv_label.grid()

        ## History frame (bottom) of Tab 1
        self.tab1_history = tk.LabelFrame(self, text="History")
        self.tab1_history.grid(column=0, row=1, columnspan=2, sticky='n,e,s,w',
                           padx=7, pady=(0, 7), ipadx=7, ipady=7)

        # contents
        self.tab1_history_label = tk.Label(self.tab1_history, text="It works.")
        self.tab1_history_label.grid()

        # finally, update time and date for labels
        self.set_time()
        self.set_date()

    def set_time(self):
        self.tab1_stime_var.set(LogicHandler.clock_ping())
        self.parent.after(1000, self.set_time)

    def set_date(self):
        self.tab1_sdate_var.set(LogicHandler.date_ping())
        self.parent.after(1000, self.set_date)

    def set_current_time(self):
        self.tab1_stime_entry.grid_remove()
        self.tab1_ct_label.grid()

    def set_time_entry(self):
        self.tab1_ct_label.grid_remove()
        self.tab1_stime_entry.grid()

    def set_current_date(self):
        self.tab1_sdate_entry.grid_remove()
        self.tab1_sdate_label.grid()

    def set_date_entry(self):
        self.tab1_sdate_label.grid_remove()
        self.tab1_sdate_entry.grid()

class HistoryFrame(tk.Frame):
    '''
    Intent:
      The "History" Frame (LabelFrame) of TabOne.

      The idea being, this frame displays a list of widgets which are
      each themselves generated by each entry that gets added to the list of
      Brass In and Brass Out button clicks. Important so that when we implement
      the logic for the Brass In and Brass Out buttons, it sends a signal to
      _this_ frame that updates the list. We'll make it a tk.StringVar() so
      Tkinter can automatically update it. A label widget's "textvariable="
      attribute updates, while the  "text=" option is a static value, set once
      at creation.
    '''
    def __init__(self, parent=None):
        super().__init__(parent)
        self.grid(sticky='n,e,s,w')
        self.parent = parent


class TabTwo(tk.Frame):
    '''
    Intent:
      This tab will be labeled "Edit I/O" for the express purpose of interacting
      with the current-day's brass database (a literal piece of brass with a
      number on it), to keep track of "employees" who are currently on-site.
      Every day will have its own separate database that gets saved into a
      folder of the current date in the format "MON YYYY", ie, "JUL 2019".
      The database itself will be saved with the file name of the full current
      date in the format "DDMONYYYY" to prevent ambiguity, ie, "04JUL2019".
      The database should save an empty copy of itself with a message to
      indicate that this is not an error, and that no contractors were in for
      that day, in the event that there really were no contractors in that day.
    '''
    pass


class TabThree(tk.Frame):
    '''
    Intent:
      This tab will be labeled "Companies" with similar functionality and layout
      of the second tab, and it will have its own database of companies.
      It will be for the collection of relevant information, for example contact
      information of safety officers and the overnight crew foreman for
      emergencies.
    '''
    pass


class TabFour(tk.Frame):
    '''
    Intent:
      This tab will be labeled "Contractors" with similar functionality and
      layout of the previous tab, and is tied into the previous database of
      companies. This way the program can quickly grab information about the
      brass # they have, if they're in, what times, company they work for, etc..
    '''
    pass


class TabFive(tk.Frame):
    '''
    Intent:
      This tab will be labeled "Reports", and will have various buttons or check
      boxes to toggle options that display in HTML the requested information
      by the users for easy printing. A possiblity (requested in the past) could
      be what contractors for x company were in on some day last week. Payroll
      doesn't want to pay contractors for time they shouldn't be paid for, if
      those people were in fact not there that day.
    '''
    pass


def run_main():
    brass_io = Brass_IO()
    handler = LogicHandler(brass_io)
    tab1 = TabOne(brass_io.tab_one)
    brass_io.mainloop()


if __name__ == '__main__':
    run_main()
Thank you.
Reply
#2
Fixed a few things, and stuff. Also, a lot of the notes in here were just for me, but I left them in just in case anyone had questions that those notes might answer.

"""
Scope of project:
   'Access control' the function to enhance with the use of software.
   It is not meant to have bells and whistles, a distraction to the job
   and a waste of memory (meant to be run on a Raspberry Pi 3B+).
   But, it must be sufficiently comfortable visually, so that eyes do
   not get easily fatigued and certain data is easy to pick out. Next
   step is to learn ttk.Style.

Separation of functions:
   Functions that work with data input from the GUI will have their
   own class. GUI elements will contain their own logic for GUI
   operations.
   Entering information by the end-user through the GUI should not
   be manipulated by the GUI classes/elements logic, only checked
   and sent.
   When an end-user clicks on buttons which modify the GUI,
   _that_logic_ should be contained within the part of the GUI that
   controls its functionality.

License:
   Free and Open Source. Use at own risk. Yadda etc..
"""

import tkinter as tk
import tkinter.ttk as ttk
import time


class LogicHandler(object):
    """
    _This_ will parse the information that is extracted from the GUI.

      Such as:
       + When exiting the app; opens a pop-up window to verify choice,
         closes all connections and saves all data.
       + At some point, perhaps provide some kind of logging functions,
         just in case...
    """
    def __init__(self):
        super().__init__()

    @staticmethod
    def clock_ping():
        return (time.strftime('%H%M'))

    @staticmethod
    def date_ping():
        return time.strftime('%d%b%Y').upper()

    @staticmethod
    def print_not_imp():
        return "Not yet implemented."


class Brass_IO(tk.Tk):
    """Main body of the GUI to which all other objects are attached."""
    def __init__(self):
        super().__init__()
        self.title = self.winfo_toplevel().title(\
            "<=| Access-Control Tracker |=>")
        ##
        self.menu_bar = tk.Menu(self)
        self.config(menu=self.menu_bar)
        #
        self.options_menu = tk.Menu(self.menu_bar, tearoff=0)
        self.menu_bar.add_cascade(label="v Options", menu=self.options_menu)
        self.options_menu.add_command(label="> Preferences",
                                      command="")
        self.options_menu.add_command(label="> Quit this app",
                                      command=self.destroy)
        #
        self.about_menu = tk.Menu(self.menu_bar, tearoff=0)
        self.menu_bar.add_cascade(label="v About", menu=self.about_menu)
        self.about_menu.add_command(label="> Tutorial (Quick Guide)",
                                    command="")
        self.about_menu.add_command(label="> Help (FAQ, search, etc.)",
                                    command="")
        self.about_menu.add_command(label="> Legal Stuff (c)",
                                    command="")
        ###
        self.main_frame = tk.Frame(self)
        self.main_frame.grid_columnconfigure(0, weight=1)
        self.main_frame.grid_rowconfigure(0, weight=1)
        self.main_frame.grid(sticky='n,e,s,w')
        ##
        self.nb = ttk.Notebook(self.main_frame)
        self.nb.grid(padx=(18,0), pady=(18,0), sticky='n,e,s,w')
        #
        self.tab_one = tk.Frame(self.nb)
        self.nb.add(self.tab_one, text='Brass I/O')
        self.tab_one.grid_columnconfigure(0, weight=1)
        self.tab_one.grid_rowconfigure(0, weight=1)
        #
        self.tab_two = tk.Frame(self.nb)
        self.nb.add(self.tab_two, text='Edit I/O')
        self.tab_two.grid_columnconfigure(0, weight=1)
        self.tab_two.grid_rowconfigure(0, weight=1)
        #
        self.tab_three = tk.Frame(self.nb)
        self.nb.add(self.tab_three, text='Companies')
        self.tab_three.grid_columnconfigure(0, weight=1)
        self.tab_three.grid_rowconfigure(0, weight=1)
        #
        self.tab_four = tk.Frame(self.nb)
        self.nb.add(self.tab_four, text='Contractors')
        self.tab_four.grid_columnconfigure(0, weight=1)
        self.tab_four.grid_rowconfigure(0, weight=1)
        #
        self.tab_five = tk.Frame(self.nb)
        self.nb.add(self.tab_five, text='Reports')
        self.tab_five.grid_columnconfigure(0, weight=1)
        self.tab_five.grid_rowconfigure(0, weight=1)


class TabOne(tk.Frame):
    """
    Intent:
      This tab will be labeled 'Brass I/O'. It will contain several
      widgets, which will log #'s in and out by time and date. Below it,
      a brief 'history' frame of the last x-number of entries. The
      back-end to this UI element should therefore send the info to a
      scheduler which puts it all into a database. Entry widgets will
      need to have certain inputs be rejected to prevent errors. This
      helps keep the database intact, and the program running as
      smoothly as possible. Python's logic and branching make rejecting
      the input from the entry label easy, and a popup window can be
      implemented to let the user know what the desired input should be.
      Possibly even a few examples.

      Two of the frames in _this_ tab will have their own class.
      (History and Quick View)
    """
    def __init__(self, parent):
        super().__init__(parent)
        self.grid(sticky='n,e,s,w')
        self.parent = parent

##        ##
##        #testing; runs once at creation of instance object.
##        #could be used to get path names for calling objects, etc..
##        #
##        self.local_var1 = self.winfo_id() #works
##        print(str(self.local_var1) + " ; a TabOne object ID (winfo_id).")
##        #
##        self.local_var2 = self.winfo_pathname(self.local_var1) #works
##        print(str(self.local_var2) + " ; TabOne object pathname.")
##        #
##        self.local_var3 = self.winfo_atom(self.local_var1) #works
##        print(str(self.local_var3) + " ; TabOne object path (winfo_atom).")
##        #
##        self.local_var4 = self.winfo_toplevel() #works
##        print(str(self.local_var4) + " ; TabOne object winfo_toplevel.")

        self.tab_one_entries = ttk.LabelFrame(self, text="Entries")
        self.tab_one_entries.grid(column=0, row=0, padx=7,
                             pady=7, ipadx=7, ipady=7)
        ## frame for brass num (entry), brass in & brass out buttons.
        self.tab1_main_top = tk.Frame(self.tab_one_entries)
        self.tab1_main_top.grid(column=0, row=0, sticky="n,e,s,w",
                                padx=5, pady=5, ipadx=6, ipady=6)
        self.tab1_main_top.grid_columnconfigure(0, weight=1)
        # contents
        self.tab1_box = ttk.Entry(self.tab1_main_top, width=10,
                                  justify='center')
        self.tab1_box.grid(column=0, row=0, sticky="n,e,s,w")
        self.tab1_button1 = ttk.Button(self.tab1_main_top, text="Brass In")
        self.tab1_button1.grid(column=1, row=0, sticky="e,w")
        self.tab1_button2 = ttk.Button(self.tab1_main_top, text="Brass Out")
        self.tab1_button2.grid(column=2, row=0, sticky="e,w")

        ## frame for current time
        self.tab1_main_mid = ttk.LabelFrame(self.tab_one_entries,
                                           text="Format: HHMM -------------- \
Enter a time:")
        self.tab1_main_mid.grid(row=1, sticky="e,w", ipadx=6, ipady=6,
                                padx=5, pady=5)
        self.tab1_main_mid.grid_columnconfigure(0, weight=0)
        self.tab1_main_mid.grid_columnconfigure(1, weight=0)
        self.tab1_main_mid.grid_columnconfigure(2, weight=0)
        self.tab1_main_mid.grid_columnconfigure(3, weight=1)
        # contents
        self.timeVar = tk.IntVar()
        self.timeVar.set(1)
        self.tab1_ctime = ttk.Radiobutton(self.tab1_main_mid,
                                          variable=self.timeVar, value=1,
                                          command=self.set_current_time)
                                                        # ^ func3 ^
        self.tab1_ctime.grid(row=1, column=0, sticky='e', padx=(6,0))
        self.tab1_ct_label = ttk.Label(self.tab1_main_mid, text="Current Time")
        self.tab1_ct_label.grid(row=1, column=1, padx=(0,8), sticky="e")
        self.tab1_stime = ttk.Radiobutton(self.tab1_main_mid,
                                          variable=self.timeVar, value=2,
                                          command=self.set_time_entry)
                                                        # ^ func4 ^
        self.tab1_stime.grid(row=1, column=2, padx=(14,0), sticky="e")
        self.tab1_stime_entry = ttk.Entry(self.tab1_main_mid, width=10,
                                          justify='center')
        self.tab1_stime_entry.grid(row=1, column=3, padx=(0,2),
                                   sticky="n,e,s,w")
        self.tab1_stime_entry.grid_remove()
        self.tab1_stime_var = tk.StringVar()
        self.tab1_ct_label = tk.Label(self.tab1_main_mid,
                                      textvariable=self.tab1_stime_var,
                                      justify='center')
        self.tab1_ct_label.grid(row=1, column=3, padx=(0,2),
                                       sticky="w,e")

        ## frame for current date
        self.tab1_main_bot = ttk.LabelFrame(self.tab_one_entries,
                                           text="Format: DDMONYYYY ------ \
Enter a date:")
        self.tab1_main_bot.grid(row=2, sticky="n,e,s,w",
                                ipadx=6, ipady=6, padx=5, pady=5)
        self.tab1_main_bot.grid_columnconfigure(0, weight=0)
        self.tab1_main_bot.grid_columnconfigure(1, weight=0)
        self.tab1_main_bot.grid_columnconfigure(2, weight=0)
        self.tab1_main_bot.grid_columnconfigure(3, weight=1)
        # contents
        self.dateVar = tk.IntVar()
        self.dateVar.set(1)
        self.tab1_cdate = ttk.Radiobutton(self.tab1_main_bot,
                                          variable=self.dateVar, value=1,
                                          command=self.set_current_date)
                                                        # ^ func5 ^
        self.tab1_cdate.grid(row=2, sticky="e", padx=(6,0))
        self.tab1_cd_label = ttk.Label(self.tab1_main_bot, text="Current Date")
        self.tab1_cd_label.grid(row=2, column=1, padx=(0,8), sticky="e")
        self.tab1_sdate = ttk.Radiobutton(self.tab1_main_bot,
                                          variable=self.dateVar, value=2,
                                          command=self.set_date_entry)
                                                        # ^ func6 ^
        self.tab1_sdate.grid(row=2, column=2, padx=(14,0), sticky='e')
        self.tab1_sdate_entry = ttk.Entry(self.tab1_main_bot, width=10,
                                          justify='center')
        self.tab1_sdate_entry.grid(row=2, column=3, padx=(0,2),
                                   sticky='n,e,s,w')
        self.tab1_sdate_entry.grid_remove()
        self.tab1_sdate_var = tk.StringVar()
        self.tab1_sdate_label = tk.Label(self.tab1_main_bot,
                                         textvariable=self.tab1_sdate_var,
                                         justify='center')
        self.tab1_sdate_label.grid(row=2, column=3, padx=(0,2), sticky='w,e')

        ## Quick View frame (top right) of tab_one
        self.tab1_qv = ttk.LabelFrame(self, text="Quick View")
        self.tab1_qv.grid(column=1, row=0, sticky='n,e,s,w',
                           padx=7, pady=7, ipadx=7, ipady=7)
        ## History frame (bottom) of tab_one
        self.tab1_history = tk.LabelFrame(self, text="History")
        self.tab1_history.grid(column=0, row=1, columnspan=2, sticky='n,e,s,w',
                           padx=7, pady=(0, 7), ipadx=7, ipady=7)
        # update labels and set the scheduler to update them every second.
        self.set_time()  # <-- func1
        self.set_date()  # <-- func2

    def set_time(self):  #func1 -->
        self.tab1_stime_var.set(LogicHandler.clock_ping())
        self.parent.after(1000, self.set_time)

    def set_date(self):  #func2 -->
        self.tab1_sdate_var.set(LogicHandler.date_ping())
        self.parent.after(1000, self.set_date)

    def set_current_time(self):  #func3 -->
        self.tab1_stime_entry.grid_remove()
        self.tab1_ct_label.grid()

    def set_time_entry(self):  #func4 -->
        self.tab1_ct_label.grid_remove()
        self.tab1_stime_entry.grid()

    def set_current_date(self):  #func5 -->
        self.tab1_sdate_entry.grid_remove()
        self.tab1_sdate_label.grid()

    def set_date_entry(self):  #func6 -->
        self.tab1_sdate_label.grid_remove()
        self.tab1_sdate_entry.grid()

class QuickView(tk.Frame):
    """
    Intent:
      The "Quick View" Frame (LabelFrame) of TabOne.
      Just a quick listing of stats.
    """
    def __init__(self, parent=None):
        super().__init__(parent)
        self.grid(sticky='n,e,s,w')
        #
        self.parent = parent
        #
        self.qv_dummylabel = tk.Label(self, text="   It still works.   ")
        self.qv_dummylabel.grid()


class History(tk.Frame):
    """
    Intent:
      The 'History' Frame (LabelFrame) of TabOne.

      The idea being, this frame displays a list of widgets which are
      each themselves generated by each entry that gets added to the
      list of Brass In and Brass Out button clicks. Important so that
      when we implement the logic for the Brass In and Brass Out
      buttons, it sends a signal to _this_ frame that updates the list.
      We'll make it a tk.StringVar() so Tkinter can automatically update
      it. A label widget's 'textvariable=' attribute updates, while the
      'text=' option is a static value, set once at creation.
    """
    def __init__(self, parent=None):
        super().__init__(parent)
        self.grid(sticky='n,e,s,w')
        #
        self.parent = parent
        #
        self.hist_dummylabel = tk.Label(self, text="   History stuff.   ")
        self.hist_dummylabel.grid()


class TabTwo(tk.Frame):
    """
    Intent:
      This tab will be labeled 'Edit I/O' for the express purpose of
      interacting with the current-day's brass database (a literal
      piece of brass with a number on it), to keep track of 'employees'
      who are currently on-site. Every day will have its own separate
      database that gets saved into a folder of the current date in the
      format 'MON YYYY', ie, 'JUL 2019'. The database itself will be
      saved with the file name of the full current date in the format
      'DDMONYYYY' to prevent ambiguity, ie, '04JUL2019'. The database
      should save an empty copy of itself with a message to indicate
      that this is not an error, and that no contractors were in for
      that day, in the event that there really were no contractors in
      that day.

      The 'Results' frame should just have a scrollable widget thing
      that allows the user to click on widgets that represent a history
      of search items. Each widget then, when <Event> happens opens up a
      web page with the requested search information, which is saved in
      the widget object for quick redisplay of the web page.
    """
    def __init__(self, parent=None):
        super().__init__(parent)
        self.parent = parent
        self.grid(sticky='n,e,s,w')
        self.grid_columnconfigure(0, weight=1)
        self.grid_rowconfigure(0, weight=1)
        self.grid_rowconfigure(1, weight=1)
        self.grid_rowconfigure(3, weight=1)
        ##
        self.search_frame = ttk.LabelFrame(self, text="Search")
        self.search_frame.grid(column=0, row=0, sticky='n,e,s,w', padx=8,
                               pady=(8,2))
        #
        self.brass_label = ttk.Label(self.search_frame, text="Brass #")
        self.brass_label.grid(column=0, row=0, sticky='e,w')
        self.brass_entry = ttk.Entry(self.search_frame)
        self.brass_entry.grid(column=1, row=0, sticky='e,w')
        self.fnam_label = ttk.Label(self.search_frame, text="First name")
        self.fnam_label.grid(column=0, row=1, sticky='e,w')
        self.fnam_entry = ttk.Entry(self.search_frame)
        self.fnam_entry.grid(column=1, row=1, sticky='e,w')
        self.lnam_label = ttk.Label(self.search_frame, text="Last name")
        self.lnam_label.grid(column=0, row=2, sticky='e,w')
        self.lnam_entry = ttk.Entry(self.search_frame)
        self.lnam_entry.grid(column=1, row=2, sticky='e,w')
        self.compnam_label = ttk.Label(self.search_frame, text="Company")
        self.compnam_label.grid(column=0, row=3, sticky='e,w')
        self.comp_select = tk.Listbox(self.search_frame)
        self.comp_select.grid(column=1, row=3, sticky='e,w')
        ##
        self.results_frame = ttk.LabelFrame(self, text="Results")
        self.results_frame.grid(column=0, row=1, sticky='n,e,s,w', padx=8,
                                pady=(2,8))
        #
        self.dummy_label1 = ttk.Label(self.results_frame,
                                     text="Put something here")
        self.dummy_label1.grid()
        ##
        self.sep_line = ttk.Separator(self, orient='horizontal')
        self.sep_line.grid(column=0, row=2, sticky='n,e,s,w', pady=(6,6))
        ##
        self.browse_frame = ttk.LabelFrame(self, text="Browse")
        self.browse_frame.grid(column=0, row=3, sticky='n,e,s,w', padx=8,
                               pady=(4,4))
        #
        self.dummy_label2 = ttk.Label(self.browse_frame,
                                     text="And something here...")
        self.dummy_label2.grid()


class TabThree(tk.Frame):
    """
    Intent:
      This tab will be labeled 'Companies' with similar functionality
      and layout of the second tab, and it will have its own database of
      companies. It will be for the collection of relevant information,
      for example contact information of safety officers and the
      overnight crew foreman for emergencies.
    """
    def __init__(self, parent=None):
        super().__init__(parent)
        self.grid(sticky='n,e,s,w')
        #
        self.parent = parent


class TabFour(tk.Frame):
    """
    Intent:
      This tab will be labeled 'Contractors' with similar functionality
      and layout of the previous tab, and is tied into the previous
      database of companies. This way the program can quickly grab
      information about the brass # they have, if they're in, what
      times, company they work for, etc..
    """
    def __init__(self, parent=None):
        super().__init__(parent)
        self.grid(sticky='n,e,s,w')
        #
        self.parent = parent


class TabFive(tk.Frame):
    """
    Intent:
      This tab will be labeled 'Reports', and will have various buttons
      or check boxes to toggle options that display in HTML the
      requested information by the users for easy printing. A possiblity
      (requested in the past) could be what contractors for x company
      were in on some day last week. Payroll doesn't want to pay
      contractors for time they shouldn't be paid for, if those people
      were in fact not there that day.
    """
    def __init__(self, parent=None):
        super().__init__(parent)
        self.grid(sticky='n,e,s,w')
        #
        self.parent = parent


def run_main():
    brass_io = Brass_IO()
    tab1 = TabOne(brass_io.tab_one)
    qv_frame = QuickView(tab1.tab1_qv)
    history_frame = History(tab1.tab1_history)
    tab2 = TabTwo(brass_io.tab_two)
    brass_io.mainloop()


if __name__ == '__main__':
    run_main()
This feels comfortable to work with.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Whatsapp stratus tracker itaybardugo 1 6,145 Feb-20-2022, 06:57 AM
Last Post: itaybardugo

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020