Spaces:
Sleeping
Sleeping
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() |