I made a really useful script that I would like to improve. It essentially keeps track of timeframes of a stock market chart and makes an overall tally. I have made it save the tally and so when I close and re-open it, it goes back to the last configuation (very important).
However, I would like to create several tabs so I can keep track of different charts (SPX, OIL, Bonds etc) and have them all be saved and automatically resort back to their last configuation each time it opens. I am having trouble doing this, so I decided to completely rebuild from scratch.
My question is, how would you go about doing this? Would tabs be a good solution, or should I simply have a menu that takes me to the various chart tallies? Or would you recommend another solution?
Another problem I am having is that the script is very long and cumbersome. I think it would be better if I broke it down into several modules. So if you have any advice in doing so, I am all ears.
The current code is as follows:
However, I would like to create several tabs so I can keep track of different charts (SPX, OIL, Bonds etc) and have them all be saved and automatically resort back to their last configuation each time it opens. I am having trouble doing this, so I decided to completely rebuild from scratch.
My question is, how would you go about doing this? Would tabs be a good solution, or should I simply have a menu that takes me to the various chart tallies? Or would you recommend another solution?
Another problem I am having is that the script is very long and cumbersome. I think it would be better if I broke it down into several modules. So if you have any advice in doing so, I am all ears.
The current code is as follows:
import tkinter as tk import json import os class TallyCounterApp: def __init__(self, root): self.root = root self.root.title("Tally Counter") self.root.overrideredirect(True) # Remove the window's title bar self.root.attributes("-topmost", True) # Initialize the total value self.total = 0 # List of timelines and their toggle values self.timelines = [ "Week", "3 Day", "1 Day", "12 Hour", "8 Hour", "6 Hour", "4 Hour", "3 Hour", "2 Hour", "1 Hour", "45 Min", "30 Min", "15 Min", "10 Min", "5 Min" ] # Store the current value for each timeline (starts at 0) self.timeline_values = {timeline: 0 for timeline in self.timelines} self.button_states = {timeline: {"plus": None, "minus": None, "zero": None} for timeline in self.timelines} # Dictionary to hold Entry, Stop Loss, and Take Profit for each timeframe self.fields = { timeline: { "entry_value": tk.DoubleVar(value=0.0), "stop_loss_value": tk.DoubleVar(value=0.0), "take_profit_value": tk.DoubleVar(value=0.0), "toggle_state": tk.StringVar(value="✖") # Initial toggle state for tick/cross } for timeline in self.timelines } # Load previous configuration if available self.load_config() # Bind mouse events to enable window dragging, but only on non-interactive areas self.root.bind("<Button-1>", self.start_move) self.root.bind("<B1-Motion>", self.do_move) # Create label to display total self.total_label = tk.Label(self.root, text=f"Total: {self.total}", font=("Arial", 24)) self.total_label.grid(row=0, column=0, columnspan=8, pady=20) # Add column labels for Entry, Stop Loss, and Take Profit self.add_column_labels() # Create buttons and entry fields for each timeline self.create_timeline_buttons() # Create Reset button self.reset_button = tk.Button(self.root, text="Reset", font=("Arial", 18), command=self.reset, width=10) self.reset_button.grid(row=len(self.timelines) + 5, column=0, columnspan=8, pady=20) # Create close button in the top right self.close_button = tk.Button(self.root, text="X", font=("Arial", 18), command=self.on_close, fg="red", width=5) self.close_button.place(relx=1.0, rely=0.0, anchor="ne") def add_column_labels(self): """Add labels for Entry, Stop Loss, and Take Profit columns.""" labels = ["Entry", "Stop Loss", "Take Profit", "✔/✖"] for i, label_text in enumerate(labels): label = tk.Label(self.root, text=label_text, font=("Arial", 14)) label.grid(row=1, column=4 + i, padx=5, pady=5) def create_timeline_buttons(self): """Create buttons and entry fields for each timeline.""" for i, timeline in enumerate(self.timelines): # Create label for the timeline label = tk.Label(self.root, text=timeline, font=("Arial", 14), anchor="w", width=10) label.grid(row=i+2, column=0, padx=10, pady=5) # Create +1, -1, and 0 buttons plus_button = tk.Button(self.root, text="+1", font=("Arial", 12), command=lambda t=timeline: self.modify_value(t, 1), width=5, bg="lightgray") plus_button.grid(row=i+2, column=1, padx=5, pady=5) minus_button = tk.Button(self.root, text="-1", font=("Arial", 12), command=lambda t=timeline: self.modify_value(t, -1), width=5, bg="lightgray") minus_button.grid(row=i+2, column=2, padx=5, pady=5) zero_button = tk.Button(self.root, text="0", font=("Arial", 12), command=lambda t=timeline: self.reset_value(t), width=5, bg="lightgray") zero_button.grid(row=i+2, column=3, padx=5, pady=5) # Store references to the buttons self.button_states[timeline]["plus"] = plus_button self.button_states[timeline]["minus"] = minus_button self.button_states[timeline]["zero"] = zero_button # Restore the previous button state from loaded config self.update_button_colors(timeline) # Create entry fields for Entry, Stop Loss, and Take Profit next to the buttons self.create_entry_fields(timeline, i+2) # Create tick/cross toggle button toggle_button = tk.Button(self.root, textvariable=self.fields[timeline]["toggle_state"], font=("Arial", 12), width=5, command=lambda t=timeline: self.toggle_state(t)) toggle_button.grid(row=i+2, column=7, padx=5, pady=5) # Disable drag for interactive elements (buttons and entry fields) plus_button.bind("<Button-1>", self.disable_move) minus_button.bind("<Button-1>", self.disable_move) zero_button.bind("<Button-1>", self.disable_move) toggle_button.bind("<Button-1>", self.disable_move) def create_entry_fields(self, timeline, row): """Create entry fields for Entry, Stop Loss, and Take Profit for each timeline.""" variables = [ self.fields[timeline]["entry_value"], self.fields[timeline]["stop_loss_value"], self.fields[timeline]["take_profit_value"] ] for i, variable in enumerate(variables): entry = tk.Entry(self.root, textvariable=variable, font=("Arial", 12), width=8) entry.grid(row=row, column=4 + i, padx=5, pady=5) # Disable drag for the entry fields entry.bind("<Button-1>", self.disable_move) def toggle_state(self, timeline): """Toggle between tick (✔) and cross (✖) for the toggle button.""" current_state = self.fields[timeline]["toggle_state"].get() new_state = "✔" if current_state == "✖" else "✖" self.fields[timeline]["toggle_state"].set(new_state) def modify_value(self, timeline, change): """Modify the timeline value by +1 or -1 and update the total.""" current_value = self.timeline_values[timeline] if change == 1: # User pressed +1 if current_value == 0: # From 0 to +1 self.total += 1 elif current_value == -1: # From -1 to +1 self.total += 2 # Remove -1, then add +1 # Set the new value to +1 self.timeline_values[timeline] = 1 self.button_states[timeline]["minus"].config(bg="lightgray") # Unhighlight -1 button self.button_states[timeline]["plus"].config(bg="green") # Highlight +1 button self.button_states[timeline]["zero"].config(bg="lightgray") # Reset 0 button color elif change == -1: # User pressed -1 if current_value == 0: # From 0 to -1 self.total -= 1 elif current_value == 1: # From +1 to -1 self.total -= 2 # Remove +1, then subtract -1 # Set the new value to -1 self.timeline_values[timeline] = -1 self.button_states[timeline]["plus"].config(bg="lightgray") # Unhighlight +1 button self.button_states[timeline]["minus"].config(bg="red") # Highlight -1 button self.button_states[timeline]["zero"].config(bg="lightgray") # Reset 0 button color self.update_labels() def reset_value(self, timeline): """Reset the timeline value to 0 and update the total.""" current_value = self.timeline_values[timeline] if current_value == 1: # If it was previously +1, subtract 1 from the total self.total -= 1 elif current_value == -1: # If it was previously -1, add 1 to the total self.total += 1 # Set the new value to 0 self.timeline_values[timeline] = 0 self.button_states[timeline]["plus"].config(bg="lightgray") # Unhighlight +1 button self.button_states[timeline]["minus"].config(bg="lightgray") # Unhighlight -1 button self.button_states[timeline]["zero"].config(bg="black") # Highlight 0 button self.update_labels() def update_labels(self): """Update the total label.""" self.total_label.config(text=f"Total: {self.total}") def update_button_colors(self, timeline): """Restore the button colors after loading config.""" current_value = self.timeline_values[timeline] if current_value == 1: self.button_states[timeline]["plus"].config(bg="green") elif current_value == -1: self.button_states[timeline]["minus"].config(bg="red") else: self.button_states[timeline]["zero"].config(bg="black") def start_move(self, event): """Start moving the window.""" self.x = event.x self.y = event.y def do_move(self, event): """Move the window.""" deltax = event.x - self.x deltay = event.y - self.y self.root.geometry(f"+{self.root.winfo_x() + deltax}+{self.root.winfo_y() + deltay}") def disable_move(self, event): """Prevent window drag when clicking inside interactive widgets.""" return def reset(self): """Reset all values to default.""" self.timeline_values = {timeline: 0 for timeline in self.timelines} for timeline in self.timelines: self.button_states[timeline]["plus"].config(bg="lightgray") self.button_states[timeline]["minus"].config(bg="lightgray") self.button_states[timeline]["zero"].config(bg="black") self.fields[timeline]["entry_value"].set(0.0) self.fields[timeline]["stop_loss_value"].set(0.0) self.fields[timeline]["take_profit_value"].set(0.0) self.fields[timeline]["toggle_state"].set("✖") # Reset toggle button to ✖ self.total = 0 self.update_labels() def on_close(self): """Save the configuration and close the application.""" self.save_config() self.root.quit() def save_config(self): """Save the current timeline values and entry fields to a config file.""" config = { "total": self.total, "timeline_values": self.timeline_values, "fields": { timeline: { "entry_value": self.fields[timeline]["entry_value"].get(), "stop_loss_value": self.fields[timeline]["stop_loss_value"].get(), "take_profit_value": self.fields[timeline]["take_profit_value"].get(), "toggle_state": self.fields[timeline]["toggle_state"].get() } for timeline in self.timelines } } with open("config.json", "w") as f: json.dump(config, f) def load_config(self): """Load the configuration from the config file if it exists.""" if os.path.exists("config.json"): with open("config.json", "r") as f: config = json.load(f) self.total = config.get("total", 0) self.timeline_values = config.get("timeline_values", {timeline: 0 for timeline in self.timelines}) fields_data = config.get("fields", {}) for timeline in self.timelines: self.fields[timeline]["entry_value"].set(fields_data.get(timeline, {}).get("entry_value", 0.0)) self.fields[timeline]["stop_loss_value"].set(fields_data.get(timeline, {}).get("stop_loss_value", 0.0)) self.fields[timeline]["take_profit_value"].set(fields_data.get(timeline, {}).get("take_profit_value", 0.0)) self.fields[timeline]["toggle_state"].set(fields_data.get(timeline, {}).get("toggle_state", "✖")) else: self.total = 0 self.timeline_values = {timeline: 0 for timeline in self.timelines} # Main execution point if __name__ == "__main__": root = tk.Tk() app = TallyCounterApp(root) root.mainloop()