from tkinter import *
from tkinter import ttk
import math
import Substance
import Utility
from Options import Options
import Physics
[docs]class PhysicsWindow:
"""
Generated by Physics Canvas interactions, when some interaction should cause a new window to open which relates to something on the PhysicsCanvas.
:param window: The main UI window
:type window: :class:`Ui.MainWindow`
"""
def __init__(self, window):
"""
constructor
"""
self.root = Tk()
# self.root.wm_attributes("-transparent", Options['windows transparent color'])
# self.root['bg'] = Options['windows transparent color']
self.window = window
self.window.additional_windows.append(self)
self.time_elapsed_since_last_update = 0
self.root.protocol("WM_DELETE_WINDOW", self.del_win)
# self.root.mainloop()
[docs] def del_win(self):
"""
Custom delete function also deletes window from :class:`Ui.Window` update references
"""
index = self.window.additional_windows.index(self)
self.window.additional_windows.pop(index)
self.root.destroy()
[docs] def update(self, interval):
"""
Set interval in Options.py to control how often these windows update.
:param interval: Time in seconds
:type interval: number
"""
self.time_elapsed_since_last_update += interval
if self.time_elapsed_since_last_update >= Options['object popup update interval']:
self.time_elapsed_since_last_update = 0
[docs]class PhysicsObjectWindow(PhysicsWindow):
"""
A window which tracks the status of a :class:`Physics.ForceObject`, showing its current x, y, velocity, etc.
Also provides buttons for deleting the object and adding an "orbiter"
:param window: The main UI window
:type window: :class:`Ui.MainWindow`
:param physics_object: The ForceObject to track
:type physics_object: :class:`Physics.ForceObject`
:param x: The screen x the window should appear
:type x: number
:param y: The screen y the window should appear
:type y: number
"""
def __init__(self, window, physics_object, x = 200, y=200):
"""
constructor
"""
PhysicsWindow.__init__(self, window)
self.root.geometry(f"+{round(x)}+{round(y)}")
self.physics_object = physics_object
id_label = ttk.Label(self.root, text='id: '+str(physics_object.canvas_id))
id_label.grid(row=0, column=0, sticky=W)
material_text = f"{physics_object.material.name}, {physics_object.mass}kg"
material_label = ttk.Label(self.root, text=material_text)
material_label.grid(row=1, columnspan=4, sticky = W)
x_label = ttk.Label(self.root, text='x: ')
x_label.grid(row=2, column=0, sticky=E)
self.x_val = ttk.Label(self.root)
self.x_val.grid(row=2, column=1, sticky=W)
y_label = ttk.Label(self.root, text='y: ')
y_label.grid(row=2, column=2, sticky=E)
self.y_val = ttk.Label(self.root)
self.y_val.grid(row=2, column=3, sticky=W)
self.velocity_label = ttk.Label(self.root)
self.velocity_label.grid(row=3, column=0, columnspan=4, sticky=W)
self.acceleration_label = ttk.Label(self.root)
self.acceleration_label.grid(row=4, column=0, columnspan=4, sticky=W)
self.net_force_label = ttk.Label(self.root)
self.net_force_label.grid(row=5, column=0, columnspan=4, sticky=W)
self.delete_button = ttk.Button(self.root, text='Delete', command=self.delete_button)
self.delete_button.grid(row=3, column=4, sticky=E)
self.add_orbiter_button = ttk.Button(self.root, text='Add Orbiter', command=self.orbiter_button)
self.add_orbiter_button.grid(row=4, column=4, sticky=E)
self.update(Options['object popup update interval'])
self.root.mainloop()
# add additional protocol to window close so it removes from open window list
[docs] def update(self, interval):
"""
Updates the displayed information.
Updates less frequently than the framerate; only as often as specified in Options.py to improve performance
:param interval: Time in seconds
:type interval: number
"""
self.time_elapsed_since_last_update += interval
if self.time_elapsed_since_last_update >= Options['object popup update interval']:
self.root.lift()
displacement = self.physics_object.displacement
x_text = f"{round(displacement.x)} m"
y_text = f"{round(displacement.y)} m"
self.x_val['text'] = x_text
self.y_val['text'] = y_text
velocity = self.physics_object.velocity
velocity_text = f"velocity: {round(velocity.magnitude)} m/s, {round(math.degrees(velocity.angle))} deg"
self.velocity_label['text'] = velocity_text
acceleration = self.physics_object.acceleration
acceleration_text = f"acceleration: {round(acceleration.magnitude)} m/s^2, {round(math.degrees(acceleration.angle))} deg"
self.acceleration_label['text'] = acceleration_text
net_force = self.physics_object.net_force_vector
net_force_text = f"net_force: {round(net_force.magnitude)} N, {round(math.degrees(net_force.angle))} deg"
self.net_force_label['text'] = net_force_text
self.time_elapsed_since_last_update = 0
[docs]class AddObjectWindow(PhysicsWindow):
"""
Opens a new window with entry fields for adding a new PhysicsObject to the canvas.
:param window: The root window
:type window: :class:`Ui.MainWindow`
:param event: A Mousevent
:type event: Tk.MouseEvent ?
"""
def __init__(self, window, event):
PhysicsWindow.__init__(self, window)
self.root.geometry(f"+{round(event.x)+300}+{round(event.y)+40}")
# title_label = ttk.Label(self.root, text='Add Physics Object')
# title_label.grid(row=0, column=0, columnspan=5, sticky= (W,E))
self.material_label = ttk.Label(self.root, text='material')
self.material_label.grid(row=1, column=0, sticky=E)
self.listbox = ttk.Spinbox(self.root, value=list(Substance.MATERIALS.keys()), state='readonly', width=11)
self.listbox.set(list(Substance.MATERIALS.keys())[0])
self.listbox.grid(row=1, column=1, sticky=W)
self.mass_label = ttk.Label(self.root, text='mass')
self.mass_label.grid(row=2, column=0, sticky=E)
self.mass_val = StringVar()
self.mass_val.set(str(Options['default mass']))
print(self.mass_val.get())
validate_key = (self.root.register(Utility.validate_number_input), '%P')
self.mass_entry = ttk.Entry(self.root, textvariable=self.mass_val, validate='key', validatecommand=validate_key, width=10)
self.mass_entry.grid(row=2, column=1, sticky=W)
self.mass_entry.insert(0, str(Options['default mass']))
self.add_button = ttk.Button(self.root, text='Add!', command=self.add_button_press)
self.add_button.grid(row=3, column=0, columnspan=3, sticky=(N,S,E,W))
self.root.mainloop()