def openObjectSelector(self): self.selector = ObjectSelector(self)
class AddObjectWindow(QtGui.QWidget): def __init__(self, world): super(AddObjectWindow, self).__init__() self.world = world self.reference = None # reference object for new object self.selector = None # variable for the selector pop-up window self.initUI() self.show() def initUI(self): self.setWindowTitle('Add/delete object') # variables self.color = QtGui.QColor(255,255,255) self.colorWidget = ColorWidget(self) # buttons btn_create = QtGui.QPushButton('Create', self) btn_color = QtGui.QPushButton('Color', self) btn_reference = QtGui.QPushButton('Reference', self) btn_delete = QtGui.QPushButton('Delete', self) # create status bar self.statusbar = QtGui.QStatusBar(self) self.statusbar.showMessage('Ready') # labels name_label = QtGui.QLabel('Name: ') mass_label = QtGui.QLabel('Mass (kg): ') radius_label = QtGui.QLabel('Radius (km): ') position_label = QtGui.QLabel('Position (km): ') velocity_label = QtGui.QLabel('Velocity (km/s): ') header_label = QtGui.QLabel('Create object') self.reference_label = QtGui.QLabel('Default') # line edits self.radius_value = QtGui.QLineEdit(self) self.name_value = QtGui.QLineEdit(self) self.mass_value = QtGui.QLineEdit(self) self.position_x = QtGui.QLineEdit(self) self.position_y = QtGui.QLineEdit(self) self.position_z = QtGui.QLineEdit(self) self.velocity_x = QtGui.QLineEdit(self) self.velocity_y = QtGui.QLineEdit(self) self.velocity_z = QtGui.QLineEdit(self) # set default parameters self.position_x.insert('0') self.position_y.insert('0') self.position_z.insert('0') self.velocity_x.insert('0') self.velocity_y.insert('0') self.velocity_z.insert('0') self.mass_value.insert('0') self.radius_value.insert('1') # default radius is one, since by default we want to be able to see the sphere # set grid layout grid = QtGui.QGridLayout() grid.addWidget(header_label,0,0) grid.addWidget(name_label, 1, 0) grid.addWidget(self.name_value, 1, 1) grid.addWidget(btn_color, 1, 2) grid.addWidget(self.colorWidget, 1, 3) grid.addWidget(mass_label, 2, 0) grid.addWidget(self.mass_value, 2, 1) grid.addWidget(btn_reference, 2,2) grid.addWidget(self.reference_label, 2,3) grid.addWidget(radius_label, 3, 0) grid.addWidget(self.radius_value, 3, 1) grid.addWidget(position_label, 4, 0) grid.addWidget(self.position_x, 4, 1) grid.addWidget(self.position_y, 4, 2) grid.addWidget(self.position_z, 4, 3) grid.addWidget(velocity_label, 5, 0) grid.addWidget(self.velocity_x, 5, 1) grid.addWidget(self.velocity_y, 5, 2) grid.addWidget(self.velocity_z, 5, 3) grid.addWidget(btn_create,8,0) grid.addWidget(btn_delete,8,1) grid.addWidget(self.statusbar,9,0,1,-1) self.setLayout(grid) # connect elements btn_create.clicked.connect(self.makeNew) btn_color.clicked.connect(self.getColor) btn_reference.clicked.connect(self.openObjectSelector) btn_delete.clicked.connect(self.deleteObject) # this function creates the new object and is connected to the create-button def makeNew(self): name = '' position = None velocity = None radius = 0 mass = 0 try: name = str(self.name_value.text()) mass = float(self.mass_value.text()) radius = float(self.radius_value.text()) if self.reference is None: position = vector(float(self.position_x.text()), float(self.position_y.text()), float(self.position_z.text())) velocity = vector(float(self.velocity_x.text()), float(self.velocity_y.text()), float(self.velocity_z.text())) else: position = vector(float(self.position_x.text()), float(self.position_y.text()), float(self.position_z.text())) + self.reference.position velocity = vector(float(self.velocity_x.text()), float(self.velocity_y.text()), float(self.velocity_z.text())) + self.reference.velocity except: self.statusbar.showMessage('Invalid arguments!') return if name=='': self.statusbar.showMessage('The new object must have a proper name!') return color = None if self.color.isValid(): color = (self.color.redF(), self.color.greenF(), self.color.blueF()) # create a color that is compatible with the visual library else: color = (1,1,1) # else use white color. This is highly unlikely to happen though. self.world.addObject(AstronomicalObject(position, velocity, mass, sphere(pos=position, radius=radius, color=color, make_trail=False), radius, self.world.show_vectors, self.world.make_trail, self.world.velocity_scale, self.world.acceleration_scale*self.world.acceleration_gain), name) self.statusbar.showMessage("Object '{}' created successfully!".format(name)) def deleteObject(self): name = str(self.name_value.text()) rval = self.world.deleteObject(name) if rval is True: self.statusbar.showMessage("Object '{}' deleted.".format(name)) else: self.statusbar.showMessage("No object '{}' found to be deleted.".format(name)) def getColor(self): self.color = self.colorWidget.getColor() def openObjectSelector(self): self.selector = ObjectSelector(self) def setReference(self, reference): if reference != 'Default': self.reference = self.world.objects[reference] self.reference_label.setText(reference) else: self.reference = None self.reference_label.setText('Default') def closeEvent(self, event): if self.selector is not None: self.selector.close() self.close()
class ControlWindow(QtGui.QWidget): def __init__(self): super(ControlWindow, self).__init__() self.world = World(self) self.simulation_on = False # used to set the simulation speed display to zero if False self.add_object_window = None self.selector = None self.collision = False self.collision_text = '' self.initUI() def initUI(self): self.setGeometry(820, 30, 300, 0) self.setWindowTitle('Control Window') # create informational elements self.statusbar = QtGui.QStatusBar(self) self.statusbar.showMessage('Ready') self.sim_speed_label = QtGui.QLabel('Simulation speed: ') self.sim_speed_value = QtGui.QLabel('0 /s') velocity_scale = QtGui.QLabel('Velocity scale') acceleration_scale = QtGui.QLabel('Acceleration scale') self.reference_label = QtGui.QLabel('Default') # create control elements # buttons btn_start = QtGui.QPushButton('Start/Stop', self) btn_load = QtGui.QPushButton('Load simulation', self) btn_reload = QtGui.QPushButton('Reload simulation', self) btn_clear = QtGui.QPushButton('Clear', self) btn_camera = QtGui.QPushButton('Camera', self) # sliders velocity_vector_scale = QtGui.QSlider(QtCore.Qt.Horizontal, self) acceleration_vector_scale = QtGui.QSlider(QtCore.Qt.Horizontal, self) acceleration_vector_gain = QtGui.QSlider(QtCore.Qt.Horizontal, self) # sets the gain value for acceleration acceleration_vector_gain.setMinimum(1) acceleration_vector_gain.setMaximum(100000) # add object window self.add_object_window = AddObjectWindow(self.world) # time step settings timestep_label = QtGui.QLabel('Timestep:') self.timestep_value_label = QtGui.QLabel('{}'.format(self.world.getTimeStep())) timestep_set_button = QtGui.QPushButton('Set', self) self.timestep_edit = QtGui.QLineEdit(self) # checkboxes self.chkbx_trails = QtGui.QCheckBox('Show trails', self) self.chkbx_vectors = QtGui.QCheckBox('Show vectors', self) # set timers self.speedtimer = QtCore.QTimer() # updates the updates per second value self.speedtimer.setInterval(1000) self.speedtimer.start() # set widget layout grid = QtGui.QGridLayout() grid.addWidget(btn_start, 0, 0) grid.addWidget(btn_load, 0, 1) grid.addWidget(btn_reload, 0, 2) grid.addWidget(btn_clear, 0, 3) grid.addWidget(self.sim_speed_label, 1, 0) grid.addWidget(self.sim_speed_value, 1, 1) grid.addWidget(timestep_label, 3,0) grid.addWidget(self.timestep_value_label, 3, 1) grid.addWidget(self.timestep_edit, 3, 2) grid.addWidget(timestep_set_button, 3, 3) grid.addWidget(self.chkbx_trails, 4,0) grid.addWidget(btn_camera, 4, 2) grid.addWidget(self.reference_label, 4, 3) grid.addWidget(self.chkbx_vectors, 4, 1) grid.addWidget(velocity_scale, 6,0) grid.addWidget(velocity_vector_scale, 6,1) grid.addWidget(acceleration_scale, 7, 0) grid.addWidget(acceleration_vector_scale, 7, 1) grid.addWidget(acceleration_vector_gain, 7, 2) grid.addWidget(self.add_object_window,8,0,1,-1) grid.addWidget(self.statusbar, 9,0,1,-1) self.setLayout(grid) # set button tooltips btn_start.setToolTip('Start/pause simulation') timestep_set_button.setToolTip('Set simulation timestep') btn_clear.setToolTip('Clear all objects') # connect controls btn_load.clicked.connect(self.loadSimulation) btn_reload.clicked.connect(self.reloadSimulation) btn_start.clicked.connect(self.startStop) btn_clear.clicked.connect(self.clearObjects) btn_camera.clicked.connect(self.openObjectSelector) self.chkbx_trails.stateChanged.connect(self.showTrails) self.chkbx_vectors.stateChanged.connect(self.showVectors) timestep_set_button.clicked.connect(self.setTimeStep) velocity_vector_scale.valueChanged.connect(self.world.setVelocityVectorScale) acceleration_vector_scale.valueChanged.connect(self.world.setAccelerationVectorScale) acceleration_vector_gain.valueChanged.connect(self.world.setAccelerationGain) # connect timer self.speedtimer.timeout.connect(self.setSimSpeedDisplay) # set visible self.show() def start(self): # call the start method of the World object to start the thread self.world.start() def setTimeStep(self): try: self.world.setTimeStep(str(self.timestep_edit.text())) except ValueError: self.statusbar.showMessage('Invalid argument for timestep') return self.timestep_value_label.setText(self.timestep_edit.text()) self.statusbar.showMessage('Ready') def setSimSpeedDisplay(self): if self.simulation_on: self.sim_speed_value.setText('{} /s'.format(self.world.speed)) else: self.sim_speed_value.setText('0 /s') if self.collision: self.collision = False self.statusbar.showMessage(self.collision_text) def loadSimulation(self): self.simulation_on = False self.world.stopSimulation() self.add_object_window.setReference('Default') self.world.loadSimulation() if self.world.errors == Loader.ERRORS_OCCURRED: self.statusbar.showMessage('Errors occurred when loading simulation. Check error log.') elif self.world.errors == Loader.OBJECTS_LOADED: self.statusbar.showMessage('Simulation loaded succesfully!') elif self.world.errors == Loader.OBJECTS_NOT_LOADED: self.statusbar.showMessage('Object loading canceled.') def reloadSimulation(self): self.simulation_on = False self.world.stopSimulation() self.add_object_window.setReference('Default') self.setReference('Default') self.world.reloadSimulation() if self.world.errors == Loader.ERRORS_OCCURRED: self.statusbar.showMessage('Errors occurred when loading simulation. Check error log.') elif self.world.errors == Loader.OBJECTS_LOADED: self.statusbar.showMessage('Simulation loaded succesfully!') elif self.world.errors == Loader.OBJECTS_NOT_LOADED: self.statusbar.showMessage('Object loading canceled.') elif self.world.errors == Loader.FILE_NOT_OPENED: self.statusbar.showMessage('File could not be loaded.') def clearObjects(self): if not self.world.paused: self.world.stopSimulation() self.simulation_on = False self.world.clearObjects() self.add_object_window.setReference('Default') self.setReference('Default') self.statusbar.showMessage('Objects cleared') def showTrails(self, state): if state == QtCore.Qt.Checked: self.world.showTrails(True) else: self.world.showTrails(False) def showVectors(self, state): if state: self.world.showVectors(True) else: self.world.showVectors(False) def startStop(self): # start/pause simulation if not self.world.paused: self.world.stopSimulation() self.simulation_on = False self.statusbar.showMessage('Simulation paused') print self.world.time_elapsed/86400 else: self.world.startSimulation() self.simulation_on = True self.statusbar.showMessage('Simulation started') def reportCollision(self, error): #self.statusbar.showMessage(error) self.collision_text = error self.collision = True self.simulation_on = False def openObjectSelector(self): self.selector = ObjectSelector(self) def setReference(self, reference): if reference != 'Default': self.world.setReference(reference) self.reference_label.setText(reference) else: self.world.setReference(None) self.reference_label.setText('Default') def closeEvent(self, event): # handle closing the program scene.visible = 0 # close the scenery window self.world.close() self.add_object_window.close() # this is necessary so that the reference selector will also close automatically if self.selector is not None: self.selector.close() self.close() event.accept()