Advertisement
Aubic

Tkinter Timer

Jun 1st, 2022
1,040
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 23.59 KB | None | 0 0
  1. import tkinter as tk
  2. from tkinter import ttk
  3.  
  4. from tkcalendar import Calendar, DateEntry
  5. import calendar
  6. import datetime
  7. from datetime import date
  8. from typing import Any
  9.  
  10. """Finds actual meet up date based on a date description
  11. For example, if given "1st Monday of January 2022", the correct meetup date is January 3, 2022.
  12. """
  13.  
  14.  
  15. # subclassing the built-in ValueError to create MeetupDayException
  16. class MeetupDayException(ValueError):
  17.     """Exception raised when the Meetup weekday and count do not result in a valid date.
  18.  
  19.    message: explanation of the error.
  20.  
  21.    """
  22.     def __init__(self, message):
  23.         self.message = message
  24.  
  25.  
  26. class MeetupDate:
  27.     """Finds actual meet up date based on a date description
  28.  
  29.    For example, if given "1st Monday of January 2022", the correct meetup date is January 3, 2022.
  30.    """
  31.  
  32.     occurrences = {'First': 1, 'Second': 2, 'Third': 3, 'Fourth': 4, 'Fifth': 5, 'Teenth': 13, 'Last': 99}
  33.     days_of_week = {'Sunday': 0, 'Monday': 1, 'Tuesday': 2, 'Wednesday': 3, 'Thursday': 4, 'Friday': 5, 'Saturday': 6}
  34.  
  35.     @staticmethod
  36.     def find_last_occurrence(year, month, week_day):
  37.         """Finds the last occurrence of week_day in the month
  38.  
  39.        :param year: the year of the meetup
  40.        :param month: the month of the meetup
  41.        :param week_day: the last
  42.        :return datetime.date: The date of the last meetup week_day
  43.        """
  44.  
  45.         # create a calendar to work with
  46.         my_calendar = calendar.Calendar(calendar.SUNDAY)
  47.  
  48.         # A 2d list that contains the days of the month in their proper positions in the week
  49.         weeks = my_calendar.monthdayscalendar(year, month)
  50.  
  51.         for week in weeks[::-1]:  # reverse the weeks to find the last occurrence
  52.             if week[week_day] != 0:  # the first time this is not zero is the last occurrence
  53.                 return date(year, month, week[week_day])
  54.  
  55.     @staticmethod
  56.     def find_teenth_occurrence(year, month, week_day):
  57.         """Finds the week_day in teens of the month. Their are 7 days in the range 13-19
  58.  
  59.        :param year: the year of the meetup
  60.        :param month: the month of the meetup
  61.        :param week_day: the day of the week that the meetup will occur
  62.        :return datetime.date: The actual date of the meetup
  63.        """
  64.  
  65.         # create a calendar to work with
  66.         my_calendar = calendar.Calendar(calendar.SUNDAY)
  67.  
  68.         # A 2d list that contains the days of the month in their proper positions in the week
  69.         weeks = my_calendar.monthdayscalendar(year, month)
  70.  
  71.         # search through the weeks until we find a day of the week with a day of the month in the teens
  72.         for week in weeks:
  73.             if 13 <= week[week_day] <= 19:
  74.                 return date(year, month, week[week_day])
  75.  
  76.     @staticmethod
  77.     def find_nth_occurrence(year, month, week_day, occurrence):
  78.         """Finds the nth week_day of the month
  79.  
  80.        :param year: The year of the meetup
  81.        :param month: The month of the meetup
  82.        :param week_day: The day of the week for the meetup
  83.        :param occurrence: The nth occurrence of the day of the week
  84.        :return datetime.date: The actual date of the meetup
  85.        """
  86.  
  87.         # create a calendar to work with
  88.         my_calendar = calendar.Calendar(calendar.SUNDAY)
  89.  
  90.         # A 2d list that contains the days of the month in their proper positions in the week
  91.         weeks = my_calendar.monthdayscalendar(year, month)
  92.  
  93.         # a counter to keep track of how many the day of the week we have seen so far
  94.         count = 0
  95.         for week in weeks:
  96.             if week[week_day] != 0:
  97.                 count += 1
  98.                 if count == occurrence:  # nth occurrence?
  99.                     return date(year, month, week[week_day])
  100.         raise MeetupDayException('That day does not exist.')
  101.  
  102.     @staticmethod
  103.     def meetup(year, month, week, day_of_week):
  104.         """Calculate the next occurrence of meetup date
  105.        :param year: The year to start looking for the next meetup
  106.        :param month: The month to start looking for the next meetup
  107.        :param week: The week of the meetup (first, second, third, fourth, fifth, teenth, last)
  108.        teenth is the days from 13 - 19
  109.        :param day_of_week: The weekday name
  110.        """
  111.         # occurrences = {'first': 1, 'second': 2, 'third': 3, 'fourth': 4, 'fifth': 5, 'teenth': 13, 'last': 99}
  112.         # days_of_week = {'Sunday': 0, 'Monday': 1, 'Tuesday': 2, 'Wednesday': 3, 'Thursday': 4, 'Friday': 5, 'Saturday': 6}
  113.         occurrence = MeetupDate.occurrences[week]
  114.         week_day = MeetupDate.days_of_week[day_of_week]
  115.  
  116.         # find the last occurrence of the day of week
  117.         if occurrence == 99:  # the last occurrence
  118.             return MeetupDate.find_last_occurrence(year, month, week_day)
  119.  
  120.         if occurrence == 13:  # the teenth day
  121.             return MeetupDate.find_teenth_occurrence(year, month, week_day)
  122.  
  123.         # the first through fifth occurrence
  124.         return MeetupDate.find_nth_occurrence(year, month, week_day, occurrence)
  125.  
  126.  
  127. class SimpleTimer(tk.Frame):
  128.     """Creates a simple countdown timer"""
  129.     def __init__(self, master=None, top_level=None, **kwargs):
  130.         super().__init__(master, **kwargs)
  131.  
  132.         self.time_left = 0
  133.         self.paused = False
  134.         self.stopped = False
  135.         self.running = False
  136.  
  137.         self.font_size = 24
  138.         # create some validation variables
  139.         vcmd = (self.register(self.validate), '%P')
  140.         ivcmd = (self.register(self.on_invalid), '%P')
  141.  
  142.         # create our text variables
  143.         self.hours_var = tk.StringVar()
  144.         self.minutes_var = tk.StringVar()
  145.         self.seconds_var = tk.StringVar()
  146.  
  147.         # create the widgets
  148.  
  149.         # self.display = CountDownDisplay(self, digits=2)
  150.         self.display_frame = ttk.Frame(self)
  151.         self.hours_entry = ttk.Entry(
  152.             self.display_frame,
  153.             width=2,
  154.             textvariable=self.hours_var,
  155.             validate='key',
  156.             validatecommand=vcmd,
  157.             invalidcommand=ivcmd,
  158.             font=('TkDefaultFont', self.font_size),
  159.         )
  160.         self.minutes_entry = ttk.Entry(
  161.             self.display_frame,
  162.             width=2,
  163.             textvariable=self.minutes_var,
  164.             validate='key',
  165.             validatecommand=vcmd,
  166.             invalidcommand=ivcmd,
  167.             font=('TkDefaultFont', self.font_size),
  168.         )
  169.         self.seconds_entry = ttk.Entry(
  170.             self.display_frame,
  171.             width=2,
  172.             textvariable=self.seconds_var,
  173.             validate='key',
  174.             validatecommand=vcmd,
  175.             invalidcommand=ivcmd,
  176.             font=('TkDefaultFont', self.font_size),
  177.         )
  178.  
  179.         # put the controls in a frame to control the spacing
  180.         self.control_frame = tk.Frame(self)
  181.         self.start_button = tk.Button(
  182.             self.control_frame,
  183.             text='\u25b6',
  184.             width=2,
  185.             font=('TkDefaultFont', self.font_size),
  186.             command=self.timer_start,
  187.         )
  188.         self.stop_button = tk.Button(
  189.             self.control_frame,
  190.             text='\u25A0',
  191.             width=2,
  192.             font=('TkDefaultFont', self.font_size),
  193.             command=self.timer_stop,
  194.             state=tk.DISABLED,
  195.         )
  196.         self.pause_button = tk.Button(
  197.             self.control_frame,
  198.             text='\u2016',
  199.             width=2,
  200.             font=('TkDefaultFont', self.font_size),
  201.             command=self.timer_pause,
  202.             state=tk.DISABLED,
  203.         )
  204.  
  205.         # layout the widgets
  206.  
  207.         # display frame
  208.         self.hours_entry.grid(row=0, column=0, padx=5, pady=5)
  209.         ttk.Separator(self.display_frame, orient='vertical').grid(row=0, column=1, sticky=(tk.N, tk.S), rowspan=2)
  210.         self.minutes_entry.grid(row=0, column=2, pady=5, padx=5)
  211.         ttk.Separator(self.display_frame, orient='vertical').grid(row=0, column=3, sticky="ns", rowspan=2)
  212.         self.seconds_entry.grid(row=0, column=4, padx=5, pady=5)
  213.         ttk.Label(self.display_frame, text='H').grid(row=1, column=0)
  214.         ttk.Label(self.display_frame, text='M').grid(row=1, column=2)
  215.         ttk.Label(self.display_frame, text='S').grid(row=1, column=4)
  216.  
  217.         self.display_frame.grid(sticky='nswe')
  218.  
  219.         # control frame
  220.         self.start_button.grid(row=0, column=0, sticky='s', pady=(10, 0))
  221.         self.pause_button.grid(row=0, column=1, sticky='s')
  222.         self.stop_button.grid(row=0, column=2, sticky='s')
  223.         self.control_frame.grid()  # (row=1, column=0, pady=(5, 10))
  224.  
  225.         # add this frame to the parent layout
  226.         # self.grid(row=0, column=0)
  227.         self.rowconfigure(0, weight=2)
  228.         self.clear_timer()
  229.  
  230.     def clear_timer(self):
  231.         """Sets the hour, minutes, seconds entry widgets to empty strings"""
  232.         self.hours_var.set('')
  233.         self.minutes_var.set('')
  234.         self.seconds_var.set('')
  235.  
  236.     def reset(self):
  237.         """Resets the timer back to it's initial condition"""
  238.         self.clear_timer()
  239.         self.set_state(tk.NORMAL)
  240.         self.running = False
  241.         self.paused = False
  242.         self.stopped = False
  243.         self.time_left = 0
  244.         self.start_button.config(state=tk.NORMAL)
  245.         self.pause_button.config(state=tk.DISABLED)
  246.         self.stop_button.config(state=tk.DISABLED)
  247.  
  248.     def get_HMS(self):
  249.         """Returns a tuple (hours, minutes, seconds)"""
  250.         seconds = self.time_left
  251.         hours = seconds // 3600
  252.         seconds -= hours * 3600
  253.         minutes = seconds // 60
  254.         seconds -= minutes * 60
  255.         return hours, minutes, seconds
  256.  
  257.     def update_display(self, hours, minutes, seconds):
  258.         """Updates the hours, minutes and seconds display
  259.  
  260.        :param hours: hours left to count down
  261.        :param minutes: minutes left to count down
  262.        :param seconds: seconds left to count down"""
  263.         self.hours_var.set(hours)
  264.         self.minutes_var.set(minutes)
  265.         self.seconds_var.set(seconds)
  266.  
  267.     def tick(self):
  268.         """Updates the time left, checks the stopped and paused flags, schedules the next call to tick"""
  269.         if self.stopped:
  270.             self.reset()
  271.             return
  272.         if not self.paused:
  273.             if self.time_left > 0:
  274.                 self.time_left -= 1
  275.             hours, minutes, seconds = self.get_HMS()
  276.             self.update_display(hours, minutes, seconds)
  277.         self.after(1000, self.tick)
  278.  
  279.     def timer_start(self):
  280.         """Sets up the timer to run and starts the callback tick"""
  281.         hours = int(self.hours_var.get()) if self.hours_var.get() else 0
  282.         minutes = int(self.minutes_var.get()) if self.minutes_var.get() else 0
  283.         seconds = int(self.seconds_var.get()) if self.seconds_var.get() else 0
  284.         self.running = True
  285.         self.set_state(tk.DISABLED)
  286.         self.pause_button.config(state=tk.NORMAL)
  287.         self.stop_button.config(state=tk.NORMAL)
  288.         self.start_button.config(state=tk.DISABLED)
  289.         self.time_left = hours * 3600 + minutes * 60 + seconds
  290.         self.tick()
  291.  
  292.     def timer_pause(self):
  293.         """Toggles the paused flag"""
  294.         self.paused = not self.paused
  295.  
  296.     def set_state(self, state):
  297.         """Changes the state of the hour, minute, second entry widgets
  298.  
  299.        :param state: The state to put the h/m/s displays in
  300.  
  301.        VALID STATES
  302.            TKINTER CONSTANTS
  303.                NORMAL | DISABLED
  304.  
  305.            STRINGS
  306.                'normal' | 'readonly'
  307.        """
  308.         self.hours_entry.config(state=state)
  309.         self.minutes_entry.config(state=state)
  310.         self.seconds_entry.config(state=state)
  311.  
  312.     def timer_stop(self):
  313.         """Sets the stopped flag and disables the stop button"""
  314.         self.stopped = True
  315.         self.stop_button.config(state=tk.DISABLED)
  316.  
  317.     def validate(self, value):
  318.         """Verifies that value is an integer in the range 0-99
  319.  
  320.        :param value: The value the widget will have if we return True"""
  321.         # can only have 2 digits
  322.         if len(value) > 2:
  323.             return False
  324.         # can only be digits
  325.         for c in value:
  326.             if not c.isdigit():
  327.                 return False
  328.         return True
  329.  
  330.     def on_invalid(self, _):
  331.         """Sounds the system bell"""
  332.         self.bell()
  333.  
  334.  
  335. class PlaceholderEntry(tk.Entry):
  336.     """Entry widget which allows displaying simple text with default text in the widget."""
  337.     def __init__(self, master=None, placeholdertext='Placeholder', placeholdercolor='gray', **kwargs):
  338.         """Construct an placeholder entry widget with the parent MASTER.
  339.  
  340.         Includes placeholder text in the widget to give information to the user
  341.  
  342.        :
  343.         Valid resource names: background, bd, bg, borderwidth, cursor,
  344.         exportselection, fg, font, foreground, highlightbackground,
  345.         highlightcolor, highlightthickness, insertbackground,
  346.         insertborderwidth, insertofftime, insertontime, insertwidth,
  347.         invalidcommand, invcmd, justify, relief, selectbackground,
  348.         selectborderwidth, selectforeground, show, state, takefocus,
  349.         textvariable, validate, validatecommand, vcmd, width,
  350.         xscrollcommand, placeholdertext, placeholdercolor."""
  351.  
  352.         super().__init__(master, **kwargs)
  353.  
  354.         self.placeholdertext = placeholdertext
  355.         self.placeholdercolor = placeholdercolor
  356.         self.default_fg_color = self['foreground']
  357.  
  358.         self.bind("<FocusIn>", self.focus_in)
  359.         self.bind("<FocusOut>", self.focus_out)
  360.  
  361.         self.put_place_holder()
  362.  
  363.     def put_place_holder(self):
  364.         self['foreground'] = self.placeholdercolor
  365.         self.insert(0, self.placeholdertext)
  366.  
  367.     def focus_in(self, *args):
  368.         if self.get() == self.placeholdertext:
  369.             self.delete('0', 'end')
  370.         if self.get() != self.placeholdertext:
  371.             self['foreground'] = self.default_fg_color
  372.  
  373.     def focus_out(self, *args):
  374.         if not self.get():
  375.             self.put_place_holder()
  376.  
  377.  
  378. class DatePicker:
  379.     def __init__(self, master=None, top_level=None, **kwargs):
  380.         self.master = master
  381.  
  382.         self.date_picker_window = tk.Toplevel(top_level)
  383.         self.date_picker_window.title('Date of Meetup')
  384.  
  385.         today = datetime.date.today()
  386.         self.calendar = Calendar(self.date_picker_window, selectmode='day', year=today.year, month=today.month, day=today.day)
  387.         self.calendar.grid(row=0, column=0, columnspan=2)
  388.         ttk.Button(self.date_picker_window, text='Ok', command=self.ok_command).grid(row=1, column=0, sticky=tk.E)
  389.         ttk.Button(self.date_picker_window, text='Cancel', command=self.cancel_command).grid(row=1, column=1, sticky=tk.W)
  390.  
  391.     def ok_command(self):
  392.         self.master.date_var.set(self.calendar.get_date())
  393.         self.date_picker_window.destroy()
  394.  
  395.     def cancel_command(self):
  396.         self.master.date_var.set(None)
  397.         self.date_picker_window.destroy()
  398.  
  399.  
  400. # TODO: make this a modal window
  401. class SingleDateSet(tk.Frame):
  402.     def __init__(self, master, top_level=None, **kwargs):
  403.         super().__init__(master, **kwargs)
  404.         self.top_level = top_level
  405.  
  406.         yvcmd = (self.register(self.validate_year), '%P')
  407.         yivcmd = (self.register(self.on_invalid_year), '%P')
  408.  
  409.         mvcmd = (self.register(self.validate_month), '%P')
  410.         mivcmd = (self.register(self.on_invalid_month), '%P')
  411.  
  412.         self.date_var = tk.StringVar()
  413.  
  414.         self.start_date = PlaceholderEntry(self, width=12, placeholdertext='mm/dd/yyyy', textvariable=self.date_var)
  415.         hours = [str(x) for x in range(1, 13)]
  416.         half_hours = []
  417.         for hour, half in zip([hour + ':00' for hour in hours], [hour + ':30' for hour in hours]):
  418.             half_hours.extend([hour, half])
  419.         half_hours = half_hours[-2:] + half_hours[:len(half_hours)-2]
  420.         combo_times = [x + ' AM' for x in half_hours] + [x + ' PM' for x in half_hours]
  421.         self.start_time = ttk.Combobox(self, values=combo_times)
  422.         self.start_time.current(0)
  423.         self.pick_date = ttk.Button(self, text='Pick Date', command=self.get_date)
  424.  
  425.         self.start_date.grid(row=0, column=0)
  426.         self.start_time.grid(row=1, column=0)
  427.         self.pick_date.grid(row=0, column=1)
  428.  
  429.     def get_date(self):
  430.         DatePicker(self, top_level=self.top_level)
  431.  
  432.     def validate_year(self, value):
  433.         if (value.strip().isdigit() and len(value) <= 4) or value == '':
  434.             return True
  435.         return False
  436.  
  437.     def on_invalid(self):
  438.         self.master.Beep()
  439.         self.master.Beep()
  440.  
  441.     def on_invalid_year(self):
  442.         pass
  443.  
  444.     def validate_month(self, v):
  445.         return True
  446.  
  447.     def on_invalid_month(self):
  448.         pass
  449.  
  450.  
  451. # TODO: make this a modal window
  452. class RecurringDateSet(tk.Frame):
  453.     def __init__(self, master, top_level=None, **kw):
  454.         super().__init__(master, **kw)
  455.  
  456.         yvcmd = (self.register(self.validate_year), '%P')
  457.         yivcmd = (self.register(self.on_invalid_year), '%P')
  458.  
  459.         mvcmd = (self.register(self.validate_month), '%P')
  460.         mivcmd = (self.register(self.on_invalid_month), '%P')
  461.  
  462.         self.start_date = PlaceholderEntry(self, width=12, placeholdertext='mm/dd/yyyy',)
  463.         hours = [str(x) for x in range(1, 13)]
  464.         half_hours = []
  465.         for hour, half in zip([hour + ':00' for hour in hours], [hour + ':30' for hour in hours]):
  466.             half_hours.extend([hour, half])
  467.         half_hours = half_hours[-2:] + half_hours[:len(half_hours)-2]
  468.         combo_times = [x + ' AM' for x in half_hours] + [x + ' PM' for x in half_hours]
  469.         self.start_time = ttk.Combobox(self, values=combo_times)
  470.         self.start_time.current(0)
  471.         self.pick_date = ttk.Button(self, text='Pick Date')
  472.  
  473.         self.start_date.grid(row=0, column=0)
  474.         self.start_time.grid(row=1, column=0)
  475.         self.pick_date.grid(row=0, column=1)
  476.         ttk.Label(self,text="recurring").grid()
  477.  
  478.     def validate_year(self, value):
  479.         if (value.strip().isdigit() and len(value) <= 4) or value == '':
  480.             return True
  481.         return False
  482.  
  483.     def on_invalid(self):
  484.         self.master.Beep()
  485.         self.master.Beep()
  486.  
  487.     def on_invalid_year(self):
  488.         pass
  489.  
  490.     def validate_month(self, v):
  491.         return True
  492.  
  493.     def on_invalid_month(self):
  494.         pass
  495.  
  496.  
  497. class MeetupTimerSet(tk.Frame):
  498.     def __init__(self, master, top_level=None, **kwargs):
  499.         super().__init__(master, **kwargs)
  500.  
  501.         self.timer_type = tk.IntVar()
  502.         ttk.Radiobutton(self, text='Single Date', value=0, variable=self.timer_type, command=self.set_timer_type).grid(sticky=tk.W)
  503.         ttk.Radiobutton(self, text='Recurring Date', value=1, variable=self.timer_type, command=self.set_timer_type).grid(sticky=tk.W)
  504.         ttk.Separator(self, orient='horizontal').grid(sticky='ew')
  505.         self.timer_type.set(0)
  506.         self.container = tk.Frame(self)
  507.         self.container.grid()
  508.         self.frames = []
  509.         self.frames.append(SingleDateSet(self.container, top_level=top_level))
  510.         self.frames.append(RecurringDateSet(self.container, top_level=top_level))
  511.  
  512.         self.set_timer_type()
  513.  
  514.         self.grid()
  515.  
  516.     def set_timer_type(self):
  517.         for child in self.container.winfo_children():
  518.             child.grid_forget()
  519.         print(self.frames[self.timer_type.get()])
  520.         self.frames[self.timer_type.get()].grid()
  521.  
  522.  
  523. class MeetupTimer(tk.Frame):
  524.     """Creates a meetup countdown timer
  525.    """
  526.     def __init__(self, master, top_level=None, **kwargs):
  527.         super().__init__(master, **kwargs)
  528.         self.font_size = 24
  529.         self.years_var = tk.StringVar(value='')
  530.         self.months_var = tk.StringVar(value='')
  531.         self.days_var = tk.StringVar(value='')
  532.         self.hours_var = tk.StringVar(value='')
  533.         self.minutes_var = tk.StringVar(value='')
  534.         self.seconds_var = tk.StringVar(value='')
  535.  
  536.         # create the widgets
  537.         # self.display = CountDownDisplay(self, ymd=True, digits=2)
  538.         ttk.Entry(
  539.             self,
  540.             state='readonly',
  541.             textvariable=self.years_var,
  542.             font=('TkDefaultFont', self.font_size),
  543.             width=2,
  544.         ).grid(column=0, row=0, padx=5, pady=5)  # years
  545.         ttk.Separator(self, orient='vertical', ).grid(column=1, row=0, rowspan=2, sticky='ns')
  546.         ttk.Entry(
  547.             self,
  548.             state='readonly',
  549.             textvariable=self.months_var,
  550.             font=('TkDefaultFont', self.font_size),
  551.             width=2
  552.         ).grid(column=2, row=0, padx=5, pady=5)  # months
  553.         ttk.Separator(self, orient='vertical').grid(column=3, row=0, rowspan=2, sticky='ns')
  554.         ttk.Entry(
  555.             self,
  556.             state='readonly',
  557.             textvariable=self.days_var,
  558.             font=('TkDefaultFont', self.font_size),
  559.             width=2
  560.         ).grid(column=4, row=0, padx=5, pady=5)  # days
  561.  
  562.         ttk.Entry(
  563.             self,
  564.             state='readonly',
  565.             textvariable=self.hours_var,
  566.             font=('TkDefaultFont', self.font_size),
  567.             width=2
  568.         ).grid(column=0, row=2, padx=5, pady=5)  # years
  569.         ttk.Separator( self, orient='vertical', ).grid(column=1, row=2, rowspan=2, sticky='ns')
  570.         ttk.Entry(
  571.             self,
  572.             state='readonly',
  573.             textvariable=self.minutes_var,
  574.             font=('TkDefaultFont', self.font_size),
  575.             width=2,
  576.         ).grid(column=2, row=2)  # months
  577.         ttk.Separator(self, orient='vertical').grid(column=3, row=2, rowspan=2, sticky='ns')
  578.         ttk.Entry(
  579.             self,
  580.             state='readonly',
  581.             textvariable=self.seconds_var,
  582.             font=('TkDefaultFont', self.font_size),
  583.             width=2,
  584.         ).grid(column=4, row=2, padx=5, pady=5)  # days
  585.  
  586.         ttk.Label(self, text='H').grid(column=0, row=3)
  587.         ttk.Label(self, text='M').grid(column=2, row=3)
  588.         ttk.Label(self, text='S').grid(column=4, row=3)
  589.  
  590.         ttk.Label(self, text='Y').grid(column=0, row=1)
  591.         ttk.Label(self, text='M').grid(column=2, row=1)
  592.         ttk.Label(self, text='D').grid(column=4, row=1)
  593.  
  594.         self.setup_button = ttk.Button(self, text='Set', command=self.set_timer)
  595.  
  596.         # add the widgets
  597.         self.setup_button.grid(row=4, column=0, columnspan=5)
  598.  
  599.         # self.grid(row=0, column=0)
  600.  
  601.     def reset(self):
  602.         pass
  603.  
  604.     def set_timer(self):
  605.         setup_window = tk.Toplevel(self.master)
  606.         setup_window.title('Set Timer')
  607.         MeetupTimerSet(setup_window)
  608.         print('hello')
  609.  
  610.  
  611. class View(tk.Frame):
  612.     def __init__(self, master, top_level=None, **kwargs):
  613.         super().__init__(master, **kwargs)
  614.  
  615.         self.rowconfigure(0, weight=2)
  616.         self.columnconfigure(0, weight=2)
  617.  
  618.         self.notebook = ttk.Notebook(self)
  619.         simple_timer = SimpleTimer(self.notebook, top_level=top_level)
  620.         meetup_timer = MeetupTimer(self.notebook, top_level=top_level)
  621.         simple_timer.grid(row=0, column=0, sticky=tk.NSEW)
  622.         meetup_timer.grid(sticky=tk.NSEW)
  623.         self.notebook.rowconfigure(0, weight=1)
  624.         self.notebook.columnconfigure(0, weight=1)
  625.         self.notebook.add(simple_timer, text='Timer')
  626.         self.notebook.add(meetup_timer, text='Meetup')
  627.         self['background'] = 'blue'
  628.         self.notebook.grid(sticky=tk.NSEW)
  629.  
  630.         self.grid(padx=10, pady=10, sticky=tk.NSEW)
  631.  
  632.  
  633. class App(tk.Tk):
  634.     def __init__(self):
  635.         super().__init__()
  636.  
  637.         self.title('Countdown Timer')
  638.  
  639.         view = View(self, top_level=self)
  640.         view.grid(padx=10, pady=10, sticky=tk.NSEW)
  641.  
  642.  
  643. if __name__ == "__main__":
  644.     app = App()
  645.     app.mainloop()
  646.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement