Adrakaris

Python Tkinter initiative tracker

Sep 22nd, 2020
761
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import tkinter as tk
  2. import copy as c
  3.  
  4. # u/PotentBeverage 22/09/2020
  5.  
  6.  
  7. # data classes
  8. class Character:
  9.     """Basic character dataclass"""
  10.  
  11.     def __init__(self, name, initiative):
  12.         self.name = name
  13.         self.initiative = initiative
  14.  
  15.     def __str__(self):
  16.         return f"{self.name} ({self.initiative})"
  17.  
  18.  
  19. # important variables
  20. orders: [Character] = [Character("End of Round", -1)]
  21.  
  22.  
  23. # functions
  24. def add_character(name: str, initiative: int):
  25.     """Adds a character to the order list"""
  26.     global orders
  27.     orders.append(Character(name, initiative))
  28.  
  29.  
  30. def remove_character(index: int):
  31.     """Removes a character from the orders list via index"""
  32.     global orders
  33.     try:
  34.         del orders[index]
  35.     except IndexError as e:
  36.         print(e)
  37.  
  38.  
  39. def sort_orders():
  40.     """Sorts the orders list based on initiative"""
  41.     global orders
  42.     orders.sort(key=lambda cha: cha.initiative, reverse=True)
  43.  
  44.  
  45. def move_character():
  46.     """Move the character in 0th place to last place"""
  47.     global orders
  48.     orders.append(orders.pop(0))
  49.  
  50.  
  51. def pretty_print(l_in):
  52.     """Pretty Print a input list"""
  53.     out = ""
  54.     for i in [str(i) for i in l_in]:
  55.         out += i + "\n"
  56.     return out
  57.  
  58.  
  59. # main tk classes
  60. class Main(tk.Frame):
  61.     def __init__(self, base):
  62.         super().__init__(base)
  63.         self.base = base
  64.         self.base.title("Initiatives")
  65.         self.base.geometry("480x480")
  66.         self.grid()
  67.  
  68.         # creating widgets
  69.         # title
  70.         self.title = tk.Label(self.base, text="Initiatives", font=("Arial", 24))
  71.         self.title.grid(column=0, columnspan=2, row=0, sticky="ew")  # east + west
  72.  
  73.         self.createform()
  74.  
  75.         self.__c = tk.Label(self.base)  # double underscore labels serve as padding with tk.grid
  76.         self.__c.grid(column=0, row=5)
  77.  
  78.         self.orders = tk.Text(self.base, width=30, height=20)
  79.         self.orders.grid(column=0, columnspan=2, row=10, sticky="ns")
  80.         self.orders.config(state=tk.DISABLED)
  81.  
  82.         self.__b = tk.Label(self.base, text="    ")
  83.         self.__b.grid(column=2, row=0)
  84.  
  85.         self.createcancel()
  86.  
  87.         self.generate = tk.Button(self.base, text="GENERATE", font=("Arial", 14), command=self.generatelist)
  88.         self.generate.grid(column=3, row=10, sticky="n")
  89.  
  90.         self.base.bind("<Return>", self.on_enter)
  91.  
  92.     def createform(self):
  93.         """Creates the entry form for adding a character to the orders list"""
  94.         self.l_name = tk.Label(self.base, text="Name")
  95.         self.l_name.grid(column=0, row=1, sticky="ew")
  96.         self.l_init = tk.Label(self.base, text="Initiative")
  97.         self.l_init.grid(column=1, row=1, sticky="ew")
  98.  
  99.         self.f_name = tk.Entry(self.base)
  100.         self.f_name.grid(column=0, row=2)
  101.         self.f_init = tk.Entry(self.base)
  102.         self.f_init.grid(column=1, row=2)
  103.  
  104.         self.__a = tk.Label(self.base)
  105.         self.__a.grid(column=0, row=3)
  106.  
  107.         self.b_addchar = tk.Button(self.base, text="Add Character", command=self.addtoform)
  108.         self.b_addchar.grid(column=0, row=4)
  109.         self.b_clear = tk.Button(self.base, text="Clear Entries", command=self.clearform)
  110.         self.b_clear.grid(column=1, row=4)
  111.  
  112.     def createcancel(self):
  113.         """Create a form which removes a character based on index"""
  114.         self.l_remv = tk.Label(self.base, text="(Remove) Index")
  115.         self.l_remv.grid(column=3, row=1)
  116.         self.f_remv = tk.Entry(self.base)
  117.         self.f_remv.grid(column=3, row=2, sticky="ew")
  118.         self.b_remv = tk.Button(self.base, text="Remove Character?", command=self.removefromform)
  119.         self.b_remv.grid(column=3, row=4)
  120.  
  121.     def clearform(self):
  122.         """Clears all data in all entry boxes and prints orders to the text component"""
  123.         self.f_init.delete(0, tk.END)
  124.         self.f_name.delete(0, tk.END)
  125.         self.f_remv.delete(0, tk.END)
  126.  
  127.         self.displayintext(pretty_print(orders))
  128.  
  129.     def addtoform(self):
  130.         """button command to add a character, interfaces with add_character()"""
  131.         try:
  132.             fi = int(self.f_init.get())
  133.         except ValueError as e:
  134.             print(e)
  135.             return
  136.         add_character(self.f_name.get(), fi)
  137.         # print("orders", [str(i) for i in orders])
  138.  
  139.         self.clearform()
  140.  
  141.     def removefromform(self):
  142.         """Button command to remove a character, interfaces with remove_character()"""
  143.         try:
  144.             ind = int(self.f_remv.get())
  145.         except ValueError as e:
  146.             print(e)
  147.             return
  148.         remove_character(ind)
  149.  
  150.         self.clearform()
  151.  
  152.     def displayintext(self, text):
  153.         """Inserts provided text into the text box widget"""
  154.         self.orders.configure(state='normal')
  155.         self.orders.delete("1.0", tk.END)
  156.         self.orders.insert(tk.END, str(text))
  157.         self.orders.configure(state='disabled')
  158.  
  159.     def on_enter(self, event):
  160.         """RETURN key shortcut to add to form"""
  161.         self.addtoform()
  162.  
  163.     def generatelist(self):
  164.         """Generates a separate window which tracks initiatives"""
  165.         sort_orders()  # sorts orders
  166.         self.generatedlist = GeneratedInitiativeTracker(self.base, orders)
  167.  
  168.  
  169. class GeneratedInitiativeTracker(tk.Toplevel):
  170.     def __init__(self, base, orders_instance):
  171.         super().__init__(base)
  172.  
  173.         self._roundnumber = 0
  174.  
  175.         # some labels to help along
  176.         self.t = tk.Label(self, text="Turn List", font=("Arial", 20))
  177.         self.t.grid(column=1, row=0, sticky="ew")  # east + west
  178.         self.rn = tk.Label(self, text=f"Round No: {self._roundnumber}", justify=tk.CENTER)
  179.         self.rn.grid(column=1, row=1)
  180.  
  181.         self.orders = c.deepcopy(orders_instance)
  182.         self.title("Initiative Tracker:")
  183.         self.buttons: [tk.Button] = []
  184.  
  185.         self.createbuttons()
  186.  
  187.         self.bind("<Return>", self.on_enter)
  188.  
  189.     def createbuttons(self):
  190.         """
  191.        Every character in orders is assigned their own button, which when pressed will move them to the
  192.        bottom of the queue. The buttons are displayed as a list going down column 0
  193.        """
  194.         for char in orders:
  195.             nb = tk.Button(self, text=str(char), command=self.movenext)
  196.             self.buttons.append(nb)
  197.  
  198.         for i in range(len(self.buttons)):
  199.             self.buttons[i].grid(row=i, column=0, sticky="ew")
  200.  
  201.     def movenext(self):
  202.         """Button interface to move them along, and increment round counterb by 1 if End of Round is pressed"""
  203.         # detect if button is end of round
  204.         if str(orders[0]) == "End of Round (-1)":
  205.             self._roundnumber += 1
  206.             self.rn["text"] = f"Round No: {self._roundnumber}"
  207.         # move the buttons
  208.         move_character()
  209.         while self.buttons:
  210.             self.buttons.pop().destroy()
  211.         self.createbuttons()
  212.  
  213.     def on_enter(self, event):
  214.         """Enter key shortcut also moves"""
  215.         self.movenext()
  216.  
  217.  
  218. # main tk loop
  219. root = tk.Tk()
  220. mwin = Main(root)
  221. mwin.mainloop()
  222.  
RAW Paste Data