#!/usr/bin/env python3 from tkinter import * from tkinter import ttk from player import Player from game import Game PLAYERS: list[Player] = [] # init tkinter root = Tk() root.title("🀄 RonRunner - Mahjong Tournament Scoring 🀄") root.geometry("800x500") # configure style style = ttk.Style() style.theme_use('clam') # configure scrollbar canvas = Canvas(root, highlightthickness=0) scrollbar = ttk.Scrollbar(root, orient='vertical', command=canvas.yview) scrollbarFrame = ttk.Frame(canvas) scrollbarFrame.bind( "", lambda e: canvas.configure(scrollregion=canvas.bbox("all")) ) canvas.create_window((0, 0), window=scrollbarFrame, anchor="nw") canvas.configure(yscrollcommand=scrollbar.set) canvas.grid(column=0, row=0, sticky="nsew") scrollbar.grid(column=1, row=0, sticky="ns") root.grid_rowconfigure(0, weight=1) root.grid_columnconfigure(0, weight=1) frm = scrollbarFrame # activate scrollbar with pad/mouse def _on_mousewheel(event): canvas.yview_scroll(int(-1*(event.delta/120)), "units") def _on_scroll_up(event): canvas.yview_scroll(-1, "units") def _on_scroll_down(event): canvas.yview_scroll(1, "units") def _bind_mousewheel(widget): widget.bind("", _on_mousewheel) widget.bind("", _on_scroll_up) widget.bind("", _on_scroll_down) for child in widget.winfo_children(): _bind_mousewheel(child) _bind_mousewheel(frm) # init ui # players ttk.Label(frm, text="Rank", font=("Helvetica", 11, "bold")).grid(column=0, row=0, padx=10, pady=10) ttk.Label(frm, text="Player", font=("Helvetica", 11, "bold")).grid(column=1, row=0, padx=10, pady=10) ttk.Label(frm, text="Score", font=("Helvetica", 11, "bold")).grid(column=2, row=0, padx=10, pady=10) entry_player_name = ttk.Entry(frm, width=30, font=("Helvetica", 10)) entry_player_name.grid(column=1, row=len(PLAYERS) + 1, padx=10, pady=10) # adding player def addPlayer(entry: Entry): txt = entry.get() if txt: PLAYERS.append(Player(txt)) entry.delete(0, END) refreshUi() btn_player_name = ttk.Button(frm, text="➕ Add", command=lambda : addPlayer(entry_player_name)) btn_player_name.grid(column=2, row=1 + len(PLAYERS), padx=10, pady=10) # tables # TODO # table history # TODO # refresh ui def refreshUi(): # remove old labels for widget in frm.winfo_children(): if widget not in [entry_player_name, btn_player_name]: info = widget.grid_info() if info.get('row', 0) > 0 and info.get('row', 0) < 100: widget.destroy() # show players PLAYERS.sort(key=lambda p : p.score, reverse=True) for i in range(len(PLAYERS)): ttk.Label(frm, text=f"{i+1}", font=("Helvetica", 10, "bold"), foreground="#FF6B6B").grid(column=0, row=i+1, padx=10, pady=8) playerLabel = ttk.Label(frm, text=PLAYERS[i].name, font=("Helvetica", 10), foreground="#0066CC") playerLabel.grid(column=1, row=i+1, padx=10, pady=8) ttk.Label(frm, text=f"{PLAYERS[i].score}", font=("Helvetica", 10, "bold"), foreground="#2ECC71").grid(column=2, row=i+1, padx=10, pady=8) # change player name def onClick(event, player=PLAYERS[i]): popup = Toplevel(root) popup.title(f"Edit - {player.name}") popup.geometry("300x150") entry = ttk.Entry(popup, width=30, font=("Helvetica", 10)) entry.insert(0, player.name) entry.grid(column=0, row=0, padx=10, pady=10) def changeName(): name = entry.get() if name and not name in [p.name for p in PLAYERS]: player.name = name entry.delete(0, END) cancelTopLevel(popup) ttk.Button(popup, text="✓ Change", command=changeName).grid(column=1, row=0, padx=5, pady=10) ttk.Button(popup, text="✕ Cancel", command=lambda : cancelTopLevel(popup)).grid(column=2, row=0, padx=5, pady=10) playerLabel.bind("", onClick) # adding player entry_player_name.grid(column=1, row=len(PLAYERS) + 1) btn_player_name.grid(column=2, row=1 + len(PLAYERS)) def cancelTopLevel(tl: Toplevel): tl.destroy() refreshUi() root.mainloop()