import tkinter as tk from tkinter import ttk, messagebox, scrolledtext from continuous_beam import ContinuousBeam import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg import numpy as np class BeamDesignApp: def __init__(self, root): self.root = root self.root.title("Continuous Beam RC Design - ACI Code") self.root.geometry("1200x800") self.beam = ContinuousBeam() self.setup_ui() def setup_ui(self): # Create main frame main_frame = ttk.Frame(self.root, padding="10") main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S)) # Configure grid weights self.root.columnconfigure(0, weight=1) self.root.rowconfigure(0, weight=1) main_frame.columnconfigure(1, weight=1) main_frame.rowconfigure(3, weight=1) # Title title_label = ttk.Label(main_frame, text="Continuous Beam RC Design", font=('Arial', 16, 'bold')) title_label.grid(row=0, column=0, columnspan=2, pady=(0, 20)) # Input frame input_frame = ttk.LabelFrame(main_frame, text="Beam Properties", padding="10") input_frame.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 10)) # Beam properties ttk.Label(input_frame, text="Beam Width (mm):").grid(row=0, column=0, sticky=tk.W) self.width_var = tk.StringVar(value="300") ttk.Entry(input_frame, textvariable=self.width_var, width=10).grid(row=0, column=1, sticky=tk.W, padx=(5, 20)) ttk.Label(input_frame, text="Beam Depth (mm):").grid(row=0, column=2, sticky=tk.W) self.depth_var = tk.StringVar(value="500") ttk.Entry(input_frame, textvariable=self.depth_var, width=10).grid(row=0, column=3, sticky=tk.W, padx=(5, 20)) ttk.Label(input_frame, text="f'c (MPa):").grid(row=1, column=0, sticky=tk.W) self.fc_var = tk.StringVar(value="28") ttk.Entry(input_frame, textvariable=self.fc_var, width=10).grid(row=1, column=1, sticky=tk.W, padx=(5, 20)) ttk.Label(input_frame, text="fy (MPa):").grid(row=1, column=2, sticky=tk.W) self.fy_var = tk.StringVar(value="420") ttk.Entry(input_frame, textvariable=self.fy_var, width=10).grid(row=1, column=3, sticky=tk.W, padx=(5, 20)) ttk.Label(input_frame, text="Cover (mm):").grid(row=2, column=0, sticky=tk.W) self.cover_var = tk.StringVar(value="40") ttk.Entry(input_frame, textvariable=self.cover_var, width=10).grid(row=2, column=1, sticky=tk.W, padx=(5, 20)) # Spans frame spans_frame = ttk.LabelFrame(main_frame, text="Spans Configuration", padding="10") spans_frame.grid(row=2, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 10)) # Span input ttk.Label(spans_frame, text="Span Length (m):").grid(row=0, column=0, sticky=tk.W) self.span_length_var = tk.StringVar(value="6.0") ttk.Entry(spans_frame, textvariable=self.span_length_var, width=10).grid(row=0, column=1, sticky=tk.W, padx=(5, 20)) ttk.Label(spans_frame, text="Distributed Load (kN/m):").grid(row=0, column=2, sticky=tk.W) self.load_var = tk.StringVar(value="25.0") ttk.Entry(spans_frame, textvariable=self.load_var, width=10).grid(row=0, column=3, sticky=tk.W, padx=(5, 20)) # Buttons button_frame = ttk.Frame(spans_frame) button_frame.grid(row=1, column=0, columnspan=4, pady=10) ttk.Button(button_frame, text="Add Span", command=self.add_span).pack(side=tk.LEFT, padx=(0, 10)) ttk.Button(button_frame, text="Clear All", command=self.clear_spans).pack(side=tk.LEFT, padx=(0, 10)) ttk.Button(button_frame, text="Design Beam", command=self.design_beam).pack(side=tk.LEFT, padx=(0, 10)) # Spans list self.spans_listbox = tk.Listbox(spans_frame, height=4) self.spans_listbox.grid(row=2, column=0, columnspan=4, sticky=(tk.W, tk.E), pady=(10, 0)) spans_frame.columnconfigure(0, weight=1) spans_frame.columnconfigure(1, weight=1) spans_frame.columnconfigure(2, weight=1) spans_frame.columnconfigure(3, weight=1) # Results frame results_frame = ttk.LabelFrame(main_frame, text="Design Results", padding="10") results_frame.grid(row=3, column=0, columnspan=2, sticky=(tk.W, tk.E, tk.N, tk.S)) results_frame.columnconfigure(0, weight=1) results_frame.rowconfigure(0, weight=1) # Results text area self.results_text = scrolledtext.ScrolledText(results_frame, width=80, height=20, font=('Courier', 9)) self.results_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S)) def add_span(self): try: length = float(self.span_length_var.get()) load = float(self.load_var.get()) if length <= 0 or load < 0: messagebox.showerror("Error", "Please enter valid values (length > 0, load >= 0)") return self.beam.add_span(length, load) # Update spans list span_text = f"Span {len(self.beam.spans)}: L={length}m, w={load}kN/m" self.spans_listbox.insert(tk.END, span_text) # Clear input fields self.span_length_var.set("") self.load_var.set("") except ValueError: messagebox.showerror("Error", "Please enter valid numeric values") def clear_spans(self): self.beam = ContinuousBeam() self.spans_listbox.delete(0, tk.END) self.results_text.delete('1.0', tk.END) def design_beam(self): if not self.beam.spans: messagebox.showwarning("Warning", "Please add at least one span") return try: # Update beam properties self.beam.beam_width = float(self.width_var.get()) self.beam.beam_depth = float(self.depth_var.get()) self.beam.fc = float(self.fc_var.get()) self.beam.fy = float(self.fy_var.get()) self.beam.cover = float(self.cover_var.get()) self.beam.d = self.beam.beam_depth - self.beam.cover # Perform design design_results = self.beam.design_beam() # Generate and display report report = self.beam.generate_report(design_results) self.results_text.delete('1.0', tk.END) self.results_text.insert('1.0', report) # Show summary dialog self.show_summary(design_results) except Exception as e: messagebox.showerror("Error", f"Design calculation failed: {str(e)}") def show_summary(self, design_results): """Show design summary in a popup window""" summary_window = tk.Toplevel(self.root) summary_window.title("Design Summary") summary_window.geometry("600x400") # Create treeview for summary tree = ttk.Treeview(summary_window, columns=('Span', 'Location', 'Moment', 'Reinforcement', 'Shear', 'Stirrups')) tree.heading('#0', text='', anchor='w') tree.heading('Span', text='Span') tree.heading('Location', text='Location') tree.heading('Moment', text='Moment (kN-m)') tree.heading('Reinforcement', text='Reinforcement') tree.heading('Shear', text='Shear (kN)') tree.heading('Stirrups', text='Stirrups') tree.column('#0', width=0, stretch=False) tree.column('Span', width=60) tree.column('Location', width=100) tree.column('Moment', width=100) tree.column('Reinforcement', width=120) tree.column('Shear', width=80) tree.column('Stirrups', width=120) for span_data in design_results: span_num = span_data['span'] for i, (reinf, stirrup) in enumerate(zip(span_data['reinforcement'], span_data['stirrups'])): if reinf['moment'] != 0 or stirrup['shear'] != 0: tree.insert('', 'end', values=( span_num if i == 0 else '', reinf['location'], f"{reinf['moment']:.2f}" if reinf['moment'] != 0 else '-', reinf['bars'] if reinf['moment'] != 0 else '-', f"{stirrup['shear']:.2f}" if stirrup['shear'] != 0 else '-', stirrup['stirrup_spacing'] if stirrup['shear'] != 0 else '-' )) tree.pack(expand=True, fill='both', padx=10, pady=10) # Close button ttk.Button(summary_window, text="Close", command=summary_window.destroy).pack(pady=10) def main(): root = tk.Tk() app = BeamDesignApp(root) root.mainloop() if __name__ == "__main__": main()