def createState(self): mainState = QState(self.fsm) connectedState = QState(QtCore.QState.ParallelStates, mainState) processBuyState = QState(connectedState) determineBuyProcessBuyState = QState(processBuyState) waitingTRlimitProcessBuyState = QState(processBuyState) print(determineBuyProcessBuyState) determineBuyProcessBuyState.addTransition(self.sigNoBuy, waitingTRlimitProcessBuyState) determineBuyProcessBuyState.addTransition(self.sigBuy, waitingTRlimitProcessBuyState) self.test_buy() determineBuyProcessBuyState.entered.connect(self.determineBuyProcessBuyStateEntered)
def __init__(self, controller: Controller, menu_state: QState): super().__init__(parent=controller.stm) global ctrl ctrl = controller common = Common(controller=ctrl) self.finish = QFinalState(self) self.addTransition(self.finished, menu_state) self.addTransition(ctrl.button['back'].clicked, self.finish) menu = ctrl.menu.menu['БТП 020'] menu_state.addTransition(menu.button['Замещение торможения'].clicked, self) self.start = Start(self) self.ppm = common.Ppm(self) self.el_breaking = common.ElBreaking(self) self.speed_60 = common.Speed60(self) self.ku_215 = common.KU215(self) self.pim = common.Pim(self) self.enter = common.Enter(state='- 0 -', parent=self) self.el_breaking_on = ElBreakingOn(self) self.measure = Measure(self) self.ok = Ok(self) self.ok_measure = OkMeasure(self) self.el_breaking_off = ElBreakingOff(self) self.show_result = ShowResult(self) self.setInitialState(self.start) self.start.addTransition(self.ppm) self.ppm.addTransition(ctrl.server_updated, self.ppm) self.ppm.addTransition(self.ppm.done, self.el_breaking) self.el_breaking.addTransition(ctrl.switch['el. braking'].low_value, self.speed_60) self.speed_60.addTransition(ctrl.switch['>60 km/h'].low_value, self.ku_215) self.ku_215.addTransition(ctrl.switch['ku 215'].high_value, self.pim) self.pim.addTransition(ctrl.server_updated, self.pim) self.pim.addTransition(self.pim.done, self.enter) self.enter.addTransition( ctrl.switch_with_neutral['enter'].state_neutral, self.el_breaking_on) self.el_breaking_on.addTransition(ctrl.server_updated, self.el_breaking_on) self.el_breaking_on.addTransition(self.el_breaking_on.done, self.measure) self.measure.addTransition(ctrl.server_updated, self.measure) self.measure.addTransition(self.measure.done, self.ok) self.ok.addTransition(ctrl.switch['ok'].high_value, self.ok_measure) self.ok_measure.addTransition(ctrl.server_updated, self.ok_measure) self.ok_measure.addTransition(ctrl.switch['ok'].low_value, self.el_breaking_off) self.el_breaking_off.addTransition(ctrl.server_updated, self.el_breaking_off) self.el_breaking_off.addTransition(self.el_breaking_off.done, self.show_result)
def __init__(self, stickMan, keyReceiver): self.m_stickMan = stickMan self.m_keyReceiver = keyReceiver # Create animation group to be used for all transitions. self.m_animationGroup = QParallelAnimationGroup() stickManNodeCount = self.m_stickMan.nodeCount() self._pas = [] for i in range(stickManNodeCount): pa = QPropertyAnimation(self.m_stickMan.node(i), 'pos') self._pas.append(pa) self.m_animationGroup.addAnimation(pa) # Set up intial state graph. self.m_machine = QStateMachine() self.m_machine.addDefaultAnimation(self.m_animationGroup) self.m_alive = QState(self.m_machine) self.m_alive.setObjectName('alive') # Make it blink when lightning strikes before entering dead animation. lightningBlink = QState(self.m_machine) lightningBlink.assignProperty(self.m_stickMan.scene(), 'backgroundBrush', Qt.white) lightningBlink.assignProperty(self.m_stickMan, 'penColor', Qt.black) lightningBlink.assignProperty(self.m_stickMan, 'fillColor', Qt.white) lightningBlink.assignProperty(self.m_stickMan, 'isDead', True) timer = QTimer(lightningBlink) timer.setSingleShot(True) timer.setInterval(100) lightningBlink.entered.connect(timer.start) lightningBlink.exited.connect(timer.stop) self.m_dead = QState(self.m_machine) self.m_dead.assignProperty(self.m_stickMan.scene(), 'backgroundBrush', Qt.black) self.m_dead.assignProperty(self.m_stickMan, 'penColor', Qt.white) self.m_dead.assignProperty(self.m_stickMan, 'fillColor', Qt.black) self.m_dead.setObjectName('dead') # Idle state (sets no properties). self.m_idle = QState(self.m_alive) self.m_idle.setObjectName('idle') self.m_alive.setInitialState(self.m_idle) # Lightning strikes at random. self.m_alive.addTransition(LightningStrikesTransition(lightningBlink)) lightningBlink.addTransition(timer.timeout, self.m_dead) self.m_machine.setInitialState(self.m_alive)
def __init__(self, stickMan, keyReceiver): self.m_stickMan = stickMan self.m_keyReceiver = keyReceiver # Create animation group to be used for all transitions. self.m_animationGroup = QParallelAnimationGroup() stickManNodeCount = self.m_stickMan.nodeCount() self._pas = [] for i in range(stickManNodeCount): pa = QPropertyAnimation(self.m_stickMan.node(i), b'pos') self._pas.append(pa) self.m_animationGroup.addAnimation(pa) # Set up intial state graph. self.m_machine = QStateMachine() self.m_machine.addDefaultAnimation(self.m_animationGroup) self.m_alive = QState(self.m_machine) self.m_alive.setObjectName('alive') # Make it blink when lightning strikes before entering dead animation. lightningBlink = QState(self.m_machine) lightningBlink.assignProperty(self.m_stickMan.scene(), 'backgroundBrush', Qt.white) lightningBlink.assignProperty(self.m_stickMan, 'penColor', Qt.black) lightningBlink.assignProperty(self.m_stickMan, 'fillColor', Qt.white) lightningBlink.assignProperty(self.m_stickMan, 'isDead', True) timer = QTimer(lightningBlink) timer.setSingleShot(True) timer.setInterval(100) lightningBlink.entered.connect(timer.start) lightningBlink.exited.connect(timer.stop) self.m_dead = QState(self.m_machine) self.m_dead.assignProperty(self.m_stickMan.scene(), 'backgroundBrush', Qt.black) self.m_dead.assignProperty(self.m_stickMan, 'penColor', Qt.white) self.m_dead.assignProperty(self.m_stickMan, 'fillColor', Qt.black) self.m_dead.setObjectName('dead') # Idle state (sets no properties). self.m_idle = QState(self.m_alive) self.m_idle.setObjectName('idle') self.m_alive.setInitialState(self.m_idle) # Lightning strikes at random. self.m_alive.addTransition(LightningStrikesTransition(lightningBlink)) lightningBlink.addTransition(timer.timeout, self.m_dead) self.m_machine.setInitialState(self.m_alive)
def createState(self): # state defintion mainState = QState(self.fsm) finalState = QFinalState(self.fsm) self.fsm.setInitialState(mainState) initState = QState(mainState) openState = QState(mainState) mainState.setInitialState(initState) standbyState = QState(openState) processingState = QState(openState) openState.setInitialState(standbyState) # transition defition initState.addTransition(self.sigComPortOpened, openState) openState.addTransition(self.sigComPortClosed, initState) standbyState.addTransition(self.sigPowerOn, processingState) processingState.addTransition(self.sigPowerOff, standbyState) initState.entered.connect(self.initStateEntered) openState.entered.connect(self.openStateEntered) standbyState.entered.connect(self.standbyStateEntered) processingState.entered.connect(self.processingStateEntered) # fsm start self.fsm.start() pass
def __init__(self, controller: Controller, menu_state: QState): super().__init__(parent=controller.stm) global ctrl ctrl = controller common = Common(controller=ctrl) self.finish = QFinalState(self) self.addTransition(self.finished, menu_state) self.addTransition(ctrl.button['back'].clicked, self.finish) menu = ctrl.menu.menu['БТП 020'] menu_state.addTransition(menu.button['Повышенная скорость'].clicked, self) self.start = Start(self) self.ppm = common.Ppm(self) self.el_breaking = common.ElBreaking(self) self.speed_60 = common.Speed60(self) self.ku_215 = common.KU215(self) self.pim = common.Pim(self) self.enter = common.Enter(state='- 0 -', parent=self) self.speed_on = SpeedOn(self) self.measure_fill = MeasureFill(self) self.speed_off = SpeedOff(self) self.measure_empty = MeasureEmpty(self) self.show_result = ShowResult(self) self.setInitialState(self.start) self.start.addTransition(self.ppm) self.ppm.addTransition(ctrl.server_updated, self.ppm) self.ppm.addTransition(self.ppm.done, self.ku_215) # self.el_breaking.addTransition(ctrl.switch['el. braking'].low_value, self.speed_60) # self.speed_60.addTransition(ctrl.switch['>60 km/h'].low_value, self.ku_215) self.ku_215.addTransition(ctrl.switch['ku 215'].high_value, self.pim) self.pim.addTransition(ctrl.server_updated, self.pim) self.pim.addTransition(self.pim.done, self.enter) self.enter.addTransition(ctrl.switch_with_neutral['km'].state_neutral, self.speed_on) self.speed_on.addTransition(ctrl.server_updated, self.speed_on) self.speed_on.addTransition(self.speed_on.done, self.measure_fill) self.measure_fill.addTransition(ctrl.server_updated, self.measure_fill) self.measure_fill.addTransition(self.measure_fill.done, self.speed_off) self.speed_off.addTransition(ctrl.server_updated, self.speed_off) self.speed_off.addTransition(self.speed_off.done, self.measure_empty) self.measure_empty.addTransition(ctrl.server_updated, self.measure_empty) self.measure_empty.addTransition(self.measure_empty.done, self.show_result)
def my_ui(self): v_box = QVBoxLayout() config_box = QGroupBox('配置') grid = QGridLayout() label_one = QLabel('当前状态') self.choose_button = QPushButton() self.machine = QStateMachine() zoom_state = QState(self.machine) shrink_state = QState(self.machine) self.machine.setInitialState(zoom_state) zoom_state.assignProperty(self.choose_button, 'text', '放大') shrink_state.assignProperty(self.choose_button, 'text', '缩小') shrink_state.addTransition(self.choose_button.clicked, zoom_state) zoom_state.addTransition(self.choose_button.clicked, shrink_state) self.machine.start() grid.addWidget(label_one, 0, 0) grid.addWidget(self.choose_button, 0, 1) grid.addWidget(QLabel('倍数'), 1, 0) slider = QSlider(Qt.Horizontal) slider.setMaximum(5) slider.setMinimum(1) slider.setTickInterval(1) slider.setTickPosition(QSlider.TicksBothSides) slider.setSingleStep(1) slider.valueChanged.connect(self.value_deal) grid.addWidget(slider, 1, 1) kind = QComboBox() for v in self.kinds: kind.addItem(v) kind.activated.connect(self.choosed) grid.addWidget(QLabel('类别:'), 2, 0) grid.addWidget(kind, 2, 1) button_show = QPushButton('显示') button_show.clicked.connect(self.show_image) config_box.setLayout(grid) v_box.addWidget(config_box) v_box.addWidget(button_show) self.setLayout(v_box) self.resize(10, 300) self.show()
def __init__(self, controller: Controller, menu_state: QState): super().__init__(parent=controller.stm) global ctrl ctrl = controller common = Common(controller=ctrl) self.finish = QFinalState(self) self.addTransition(self.finished, menu_state) self.addTransition(ctrl.button['back'].clicked, self.finish) menu = ctrl.menu.menu['БТП 020'] menu_state.addTransition(menu.button['Время снижения'].clicked, self) self.start = Start(self) self.ppm = common.Ppm(self) self.el_breaking = common.ElBreaking(self) self.speed_60 = common.Speed60(self) self.ku_215 = common.KU215(self) self.enter = common.Enter(state='КУ', parent=self) self.handle_position_four = common.HandlePositionFour(self) self.handle_position_zero = HandlePositionZero(self) self.measure = Measure(self) self.show_result = ShowResult(self) self.setInitialState(self.start) self.start.addTransition(self.ppm) self.ppm.addTransition(ctrl.server_updated, self.ppm) self.ppm.addTransition(self.ppm.done, self.el_breaking) self.el_breaking.addTransition(ctrl.switch['el. braking'].low_value, self.speed_60) self.speed_60.addTransition(ctrl.switch['>60 km/h'].low_value, self.ku_215) self.ku_215.addTransition(ctrl.switch['ku 215'].high_value, self.enter) self.enter.addTransition(ctrl.switch_with_neutral['enter'].state_two, self.handle_position_four) self.handle_position_four.addTransition(ctrl.server_updated, self.handle_position_four) self.handle_position_four.addTransition(self.handle_position_four.done, self.handle_position_zero) self.handle_position_zero.addTransition(ctrl.server_updated, self.handle_position_zero) self.handle_position_zero.addTransition(self.handle_position_zero.done, self.measure) self.measure.addTransition(ctrl.server_updated, self.measure) self.measure.addTransition(self.measure.done, self.show_result)
def __init__(self, controller: Controller, menu_state: QState): super().__init__(parent=controller.stm) global ctrl ctrl = controller common: Common = Common(controller=ctrl) self.finish = QFinalState(self) self.addTransition(self.finished, menu_state) menu = ctrl.menu.menu['БТП 020'] self.addTransition(ctrl.button['back'].clicked, self.finish) menu_state.addTransition(menu.button['Подготовка'].clicked, self) self.start = Start(self) self.ppm = common.Ppm(self) self.install_ku = InstallKU(self) self.ku_215 = common.KU215(self) self.pim = common.Pim(self) self.tank = common.Tank(state='СБРОС', parent=self) self.el_breaking = common.ElBreaking(self) self.speed_60 = common.Speed60(self) self.set_bto = SetBTO(self) self.connect_btp = ConnectBTP(self) self.enable_menu = EnableMenu(self) self.setInitialState(self.start) self.start.addTransition(self.install_ku) self.install_ku.addTransition(ctrl.button['yes'].clicked, self.ku_215) self.ku_215.addTransition(ctrl.switch['ku 215'].high_value, self.ppm) self.ppm.addTransition(ctrl.server_updated, self.ppm) self.ppm.addTransition(self.ppm.done, self.pim) self.pim.addTransition(ctrl.server_updated, self.pim) self.pim.addTransition(self.pim.done, self.tank) self.tank.addTransition(ctrl.switch_with_neutral['tank'].state_two, self.el_breaking) self.el_breaking.addTransition(ctrl.switch['el. braking'].low_value, self.speed_60) self.speed_60.addTransition(ctrl.switch['>60 km/h'].low_value, self.set_bto) self.set_bto.addTransition(ctrl.button['yes'].clicked, self.connect_btp) self.connect_btp.addTransition(ctrl.button['yes'].clicked, self.enable_menu) self.enable_menu.addTransition(self.finish)
def __init__(self, controller: Controller, menu_state: QState): super().__init__(parent=controller.stm) global ctrl ctrl = controller common = Common(controller=ctrl) self.finish = QFinalState(self) self.addTransition(self.finished, menu_state) self.addTransition(ctrl.button['back'].clicked, self.finish) menu = ctrl.menu.menu['БТП 020'] menu_state.addTransition(menu.button['Герметичность'].clicked, self) self.start = Start(self) self.ppm = common.Ppm(self) self.el_breaking = common.ElBreaking(self) self.speed_60 = common.Speed60(self) self.ku_215 = common.KU215(self) self.enter = common.Enter(state='КУ', parent=self) self.handle_position_four = common.HandlePositionFour(self) self.check = Check(self) self.yes = Yes(self) self.no = No(self) self.setInitialState(self.start) self.start.addTransition(self.ppm) self.ppm.addTransition(ctrl.server_updated, self.ppm) self.ppm.addTransition(self.ppm.done, self.el_breaking) self.el_breaking.addTransition(ctrl.switch['el. braking'].low_value, self.speed_60) self.speed_60.addTransition(ctrl.switch['>60 km/h'].low_value, self.ku_215) self.ku_215.addTransition(ctrl.switch['ku 215'].high_value, self.enter) self.enter.addTransition(ctrl.switch_with_neutral['enter'].state_two, self.handle_position_four) self.handle_position_four.addTransition(ctrl.server_updated, self.handle_position_four) self.handle_position_four.addTransition(self.handle_position_four.done, self.check) self.check.addTransition(ctrl.button['yes'].clicked, self.yes) self.check.addTransition(ctrl.button['no'].clicked, self.no) self.yes.addTransition(self.finish) self.no.addTransition(self.finish)
def createState(self): # state defintion mainState = QState(self.fsm) finalState = QFinalState(self.fsm) self.fsm.setInitialState(mainState) initState = QState(mainState) standbyState = QState(mainState) #transition defition mainState.setInitialState(initState) mainState.addTransition(self.sigStateStop, finalState) initState.addTransition(self.sigInitOk, standbyState) standbyState.addTransition(self.sigError, initState) # #state entered slot connect mainState.entered.connect(self.mainStateEntered) initState.entered.connect(self.initStateEntered) standbyState.entered.connect(self.standbyStateEntered) finalState.entered.connect(self.finalStateEntered) #fsm start self.fsm.start() pass
def gen_output_widget(self): if self._name != "__none__": # Each output is a tuple [QPushButton, QStateMachine] self.output_widget = (QPushButton(), QStateMachine()) self.output_widget[0].setStyleSheet( "background-color: #dddddd; border-style: solid; border-width: 1px; border-color: #aaaaaa; padding: 7px;" ) # Create output states output_off = QState() output_on = QState() # Attach states to output button and define state transitions output_off.assignProperty(self.output_widget[0], 'text', "%s Output On" % self._name.split()[1]) output_off.addTransition(self.output_widget[0].clicked, output_on) output_off.entered.connect(self.exec_output_off) output_on.assignProperty(self.output_widget[0], 'text', '%s Output Off' % self._name.split()[1]) output_on.addTransition(self.output_widget[0].clicked, output_off) output_on.entered.connect(self.exec_output_on) # Add states, set initial state, and start machine self.output_widget[1].addState(output_off) self.output_widget[1].addState(output_on) self.output_widget[1].setInitialState(output_off) self.output_widget[1].start() else: self.output_widget = (QPushButton(), False) self.output_widget[0].setStyleSheet( "background-color: #dddddd; border-style: solid; border-width: 1px; border-color: #aaaaaa; padding: 7px;" ) self.output_widget[0].setEnabled(False) self.output_widget[0].setText("Keithley not Initialized")
def twoStateButton(name,stateMachine,action,*states): st = QStateMachine() a1,a2 = states s1,s2 = QState(),QState() icon1 = QIcon(Icons + a1[1]) icon2 = QIcon(Icons + a2[1]) s1.setObjectName(a1[0]) s2.setObjectName(a2[0]) s1.assignProperty(action, "icon", icon1) s2.assignProperty(action, "icon", icon2) s1.assignProperty(action, "text", a1[0]) s2.assignProperty(action, "text", a2[0]) s1.addTransition(action.triggered, s2) s2.addTransition(action.triggered, s1) st.addState(s1) st.addState(s2) st.setInitialState(s1) stateMachine[name] = st st.start()
def __init__(self): QWidget.__init__(self) style1 = "background-color: red" style2 = "background-color: black" animation = QPropertyAnimation(self, b'styleSheet') animation.setDuration(5) state1 = QState() state2 = QState() state1.assignProperty(self, 'styleSheet', style1) state2.assignProperty(self, 'styleSheet', style2) state1.addTransition(state1.propertiesAssigned, state2) state2.addTransition(state2.propertiesAssigned, state1) self.machine = QStateMachine() self.machine.addDefaultAnimation(animation) self.machine.addState(state1) self.machine.addState(state2) self.machine.setInitialState(state1) self.machine.start()
def __init__(self, controller: Controller, menu_state: QState): super().__init__(parent=controller.stm) global ctrl ctrl = controller self.finish = QFinalState(self) self.addTransition(self.finished, menu_state) self.addTransition(ctrl.button['back'].clicked, self.finish) menu = ctrl.menu.menu['БТП 020'] menu_state.addTransition(menu.button['Завершение'].clicked, self) self.start = Start(self) self.air = Air(self) self.ku_215_off = KU215Off(self) self.disconnect_bto = DisconnectBTO(self) self.report = Report(parent=self, controller=controller) self.setInitialState(self.start) self.start.addTransition(self.air) self.air.addTransition(ctrl.button['yes'].clicked, self.ku_215_off) self.ku_215_off.addTransition(ctrl.switch['ku 215'].low_value, self.disconnect_bto) self.disconnect_bto.addTransition(ctrl.button['yes'].clicked, self.report)
def __init__(self, controller: Controller, menu: QState): super().__init__(parent=controller.stm) global ctrl ctrl = controller self.finish = QFinalState(self) self.addTransition(self.finished, menu) self.reset = Reset(self) self.disable_menu = DisableMenu(self) self.report_data = ReportData(self) self.menu = Menu(self) menu.addTransition( ctrl.menu.menu['Главное меню'].button['БТП 020'].clicked, self) self.setInitialState(self.reset) self.reset.addTransition(self.disable_menu) self.disable_menu.addTransition(self.report_data) self.report_data.addTransition(ctrl.button['back'].clicked, self.finish) self.report_data.addTransition(ctrl.menu.prepare_menu.done.clicked, self.menu) self.menu.addTransition(ctrl.button['back'].clicked, self.finish) self.prepare = Prepare(controller=ctrl, menu_state=self.menu) self.auto_breaking = AutoBreaking(controller=ctrl, menu_state=self.menu) self.kvt_breaking = KvtBreaking(controller=ctrl, menu_state=self.menu) self.filling = Filling(controller=ctrl, menu_state=self.menu) self.tightness = Tightness(controller=ctrl, menu_state=self.menu) self.emptying = Emptying(controller=ctrl, menu_state=self.menu) self.substitution = Substitution(controller=ctrl, menu_state=self.menu) self.speed = Speed(controller=ctrl, menu_state=self.menu) self.ending = Ending(controller=ctrl, menu_state=self.menu) self.ending.report.addTransition(ctrl.report.exit.clicked, self.finish) self.ending.report.addTransition(ctrl.button['back'].clicked, self.finish)
def __init__(self, controller: Controller, menu_state: QState): super().__init__(parent=controller.stm) global ctrl ctrl = controller common = Common(controller=ctrl) self.finish = QFinalState(self) self.addTransition(self.finished, menu_state) self.addTransition(ctrl.button['back'].clicked, self.finish) menu = ctrl.menu.menu['БТП 020'] menu_state.addTransition(menu.button['торможение автоматическое'].clicked, self) self.start = Start(self) self.pim = common.Pim(self) self.check_1 = Check(stage=0, parent=self) self.check_2 = Check(stage=1, parent=self) self.check_3 = Check(stage=2, parent=self) self.check_4 = Check(stage=3, parent=self) self.check_5 = Check(stage=4, parent=self) self.check_6 = Check(stage=5, parent=self) self.check_7 = Check(stage=6, parent=self) self.check_8 = Check(stage=7, parent=self) self.show_result = ShowResult(parent=self) self.setInitialState(self.start) self.start.addTransition(self.pim) self.pim.addTransition(ctrl.server_updated, self.pim) self.pim.addTransition(self.pim.done, self.check_1) self.check_1.addTransition(self.check_1.finished, self.check_2) self.check_2.addTransition(self.check_2.finished, self.check_3) self.check_3.addTransition(self.check_3.finished, self.check_4) self.check_4.addTransition(self.check_4.finished, self.check_5) self.check_5.addTransition(self.check_5.finished, self.check_6) self.check_6.addTransition(self.check_6.finished, self.check_7) self.check_7.addTransition(self.check_7.finished, self.check_8) self.check_8.addTransition(self.check_8.finished, self.show_result) self.show_result.addTransition(ctrl.button['yes'].clicked, self.finish)
def init_ui(self): vbox = QVBoxLayout() button1 = QPushButton('fuck1') vbox.addWidget(button1) button1.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) vbox.setContentsMargins(80, 80, 80, 80) self.setLayout(vbox) machine = QStateMachine(self) s1 = QState() s1.assignProperty(button1, "text", "Outside") s2 = QState() s2.assignProperty(button1, "text", "Inside") enter_transition = QEventTransition(button1, QEvent.Enter) enter_transition.setTargetState(s2) s1.addTransition(enter_transition) leave_transition = QEventTransition(button1, QEvent.Leave) leave_transition.setTargetState(s1) s2.addTransition(leave_transition) s3 = QState() s3.assignProperty(button1, 'text', 'Pressing...') press_transition = QEventTransition(button1, QEvent.MouseButtonPress) press_transition.setTargetState(s3) s2.addTransition(press_transition) release_transition = QEventTransition(button1, QEvent.MouseButtonRelease) release_transition.setTargetState(s2) s3.addTransition(release_transition) machine.addState(s1) machine.addState(s2) machine.addState(s3) machine.setInitialState(s1) machine.start()
charging_ad_phase_3A = tcs_statemashina.charging.ad.Phase_3A( charging_ad_phase_3) charging_ad_phase_3B = tcs_statemashina.charging.ad.Phase_3B( charging_ad_phase_3) charging_ad_phase_3.setInitialState(charging_ad_phase_3A) charging_ad_phase_3A.addTransition(tcs.temperatureReached, charging_ad_phase_3B) charging_ad_phase_3B.addTransition(tcs.powerReached, neutral) charging_ad_phase_2.addTransition(tcs.temperatureReached, charging_ad_phase_3) charging_ec = tcs_statemashina.charging.ec.Main(charging) charging_ec_phase_1A = tcs_statemashina.charging.ec.Phase_1A(charging_ec) charging_ec.setInitialState(charging_ec_phase_1A) charging.addTransition(tcs.error, neutral) TCSstate.setInitialState(startingpoint) TCSstate.start() timer = QTimer() timer.timeout.connect(TCSstate.stop_timers) timer.timeout.connect(app.quit) timer.start(100000) # This is catcher to catch the program from stopping before all is finished. app.exec_()
class StartTuto(QDialog): def __init__(self): super(StartTuto, self).__init__() QDialog.__init__(self) self.Next = 0 self.setWindowFlags(Qt.FramelessWindowHint) self.setAttribute(Qt.WA_TranslucentBackground, True) self.setWindowTitle("لنتعلم معا") self.font = QFont('abdo salem') self.font.setPointSize(20) self.font.setBold(True) self.ex = QPushButton(self) self.ex.setFont(self.font) self.ex.setGeometry(400 + 80, 450, 150, 50) self.ex.setText('خروج') self.ex.setStyleSheet( "QPushButton:hover{background-color:rgb(241, 90, 36);border:5px solid rgb(0, 97, 157);}\n" "QPushButton{color:white;background-color: rgb(50, 50, 50);border:5px solid rgb(255, 255, 255);}QPushButton:pressed{color:white;background-color: rgb(50, 50, 50);border:5px solid rgb(255, 255, 255);}\n" "") self.ex.clicked.connect(self.Exit) self.hm = QPushButton(self) self.hm.setFont(self.font) self.hm.setGeometry(200 + 80, 450, 150, 50) self.hm.setText('الرئيسية') self.hm.setStyleSheet( "QPushButton:hover{background-color:rgb(241, 90, 36);border:5px solid rgb(0, 97, 157);}\n" "QPushButton{color:white;background-color: rgb(50, 50, 50);border:5px solid rgb(255, 255, 255);}QPushButton:pressed{color:white;background-color: rgb(50, 50, 50);border:5px solid rgb(255, 255, 255);}\n" "") self.hm.clicked.connect(self.home) self.resize(925, 500) self.Ind = [ 'data', 'if', 'for', 'while', 'def', 'class', 'oop', 'exp', 'prj2', 'prj3', 'st' ] self.names = { 'home': [ 'المتغير و\n أنواع البيانات', 'الجملة الشرطية\nIF', 'حلقة التقسيم\nFOR', 'حلقة مادام\nWHILE', 'الدالة\nDEF', 'الفئة\nClass', 'البرمجة كائنية\nالتوجه OOP', 'العبارات', 'المشروع الاول\nRANGE', 'المشروع الثاني\nStr', 'ابدء' ], 'data': [ 'المتغير', 'الأحرف ', 'الأرقام ', 'القائمة', 'القاموس', 'الخطأ\nالصحيح', 'دوال \nانواع البيانات', 'الأمثلة' ], 'if': [ 'الجملة الشرطية\nIF', 'ادوات المقارنة', 'استعمالات\n ELIF و ELSE' ], 'for': ['فكرة \nFOR', 'استعمالات \nFOR', 'امثلة'], 'while': ['فكرة \nWHILE', 'استعمالات \nWHILE', 'امثلة'], 'def': [ 'دالة بسيطة', 'arg\nدالة مع', '*arg\nدالة مع', 'دالة مع\n**kwargs' ], 'class': ['فئة بسيطة\n مع متغير', 'فئة بسيطة\n مع دالة'], 'oop': ['البناء\n__init__', 'خاصية الاراثة', 'دالة\nsuper()'], 'exp': ['عبارة\nreturn', 'عبارة\nassert', 'عبارة\nyield'], 'prj2': ['المشروع'], 'prj3': ['محاكات\nCount', 'محاكات\nFind', 'تطوير\nFind'], 'st': 'exit' } self.Home() def Home(self): self.items = [] for i in range(len(self.names['home'])): item = QPushButton(self) item.setText(self.names['home'][i]) item.setGeometry(395, 350, 120, 80) item.setStyleSheet( "QPushButton:hover{background-color:rgb(241, 90, 36);border:5px solid rgb(0, 97, 157);}\n" "QPushButton{color:white;background-color: rgb(50, 50, 50);border:5px solid rgb(255, 255, 255);}QPushButton:pressed{color:white;background-color: rgb(50, 50, 50);border:5px solid rgb(255, 255, 255);}\n" "") self.font.setPointSize(15) item.setFont(self.font) self.items.append(item) exec("""item.clicked.connect(partial(self.IND,i=%i))""" % (i)) self.rootState = QState() self.tiledState = QState(self.rootState) self.centeredState = QState(self.rootState) for i, item in enumerate(self.items): self.tiledState.assignProperty( item, 'pos', QPointF(((i % 6) * 5.3) * 30, ((i // 6) * 5.3) * 30)) self.centeredState.assignProperty(item, 'pos', QPointF()) self.states = QStateMachine() self.states.addState(self.rootState) self.states.setInitialState(self.rootState) self.rootState.setInitialState(self.centeredState) self.group = QParallelAnimationGroup() for i, item in enumerate(self.items): anim = QPropertyAnimation(item, b'pos') anim.setStartValue(QPoint(400, 300)) anim.setDuration(750 + i * 25) anim.setEasingCurve(QEasingCurve.InOutBack) self.group.addAnimation(anim) for u in self.items: trans = self.rootState.addTransition(u.clicked, self.tiledState) trans.addAnimation(self.group) self.states.start() def Exit(self): open('Files/choice', 'w').write('exit') self.close() def home(self): open('Files/choice', 'w').write('home') self.close() def IND(self, i): open('Files/choice', 'a').write(str(i)) if self.Next != 2: self.Next += 1 if self.names[self.Ind[i]] != 'exit': a = self.names[self.Ind[i]] k = 0 for i in self.items[0:len(a)]: i.setText(a[k]) k += 1 for i in self.items[len(a):]: i.hide() else: self.items[-1].hide() else: self.close()
state3.assignProperty(p1, 'pos', QPointF(0, 5)) state3.assignProperty(p2, 'pos', QPointF(0, 5 + 64 + 5)) state3.assignProperty(p3, 'pos', QPointF(5, 5 + (64 + 5) + 64)) state3.assignProperty(p4, 'pos', QPointF(5 + 64 + 5, 5)) state3.assignProperty(p5, 'pos', QPointF(5 + 64 + 5, 5 + 64 + 5)) state3.assignProperty(p6, 'pos', QPointF(5 + 64 + 5, 5 + (64 + 5) + 64)) state3.assignProperty(widget, 'geometry', QRectF(138, 5, 400 - 138, 200)) state3.assignProperty(box, 'geometry', QRect(5, 205, 400, 90)) state3.assignProperty(p1, 'opacity', 1.0) state3.assignProperty(p2, 'opacity', 1.0) state3.assignProperty(p3, 'opacity', 1.0) state3.assignProperty(p4, 'opacity', 1.0) state3.assignProperty(p5, 'opacity', 1.0) state3.assignProperty(p6, 'opacity', 1.0) t1 = state1.addTransition(button.clicked, state2) animation1SubGroup = QSequentialAnimationGroup() animation1SubGroup.addPause(250) animation1SubGroup.addAnimation(QPropertyAnimation(box, b'geometry', state1)) t1.addAnimation(animation1SubGroup) t1.addAnimation(QPropertyAnimation(widget, b'geometry', state1)) t1.addAnimation(QPropertyAnimation(p1, b'pos', state1)) t1.addAnimation(QPropertyAnimation(p2, b'pos', state1)) t1.addAnimation(QPropertyAnimation(p3, b'pos', state1)) t1.addAnimation(QPropertyAnimation(p4, b'pos', state1)) t1.addAnimation(QPropertyAnimation(p5, b'pos', state1)) t1.addAnimation(QPropertyAnimation(p6, b'pos', state1)) t1.addAnimation(QPropertyAnimation(p1, b'rotation', state1)) t1.addAnimation(QPropertyAnimation(p2, b'rotation', state1)) t1.addAnimation(QPropertyAnimation(p3, b'rotation', state1)) t1.addAnimation(QPropertyAnimation(p4, b'rotation', state1))
view.setWindowFlags(Qt.FramelessWindowHint) view.show() states = QStateMachine() states.addState(rootState) states.setInitialState(rootState) rootState.setInitialState(centeredState) group = QParallelAnimationGroup() for i, item in enumerate(items): anim = QPropertyAnimation(item, b'pos') anim.setDuration(750 + i * 25) anim.setEasingCurve(QEasingCurve.InOutBack) group.addAnimation(anim) trans = rootState.addTransition(moveButton.pressed, moveState) trans.addAnimation(group) trans = rootState.addTransition(centeredButton.pressed, centeredState) trans.addAnimation(group) timer = QTimer() timer.start(125) timer.setSingleShot(True) trans = rootState.addTransition(timer.timeout, centeredState) trans.addAnimation(group) states.start() # Draggable Cards' Window mainWidget = QWidget()
def init_log_sm(self): self.log_state = QStateMachine() pre_system = QState() pre_event = QState() post_event = QState() self.log_state.addState(pre_system) self.log_state.addState(pre_event) self.log_state.addState(post_event) self.log_state.setInitialState(pre_system) pre_system.assignProperty(self.events, "enabled", False) pre_system.assignProperty(self.compass, "enabled", False) pre_system.assignProperty(self.exact_angle, "enabled", False) pre_event.assignProperty(self.events, "enabled", True) pre_event.assignProperty(self.compass, "enabled", False) pre_event.assignProperty(self.exact_angle, "enabled", False) post_event.assignProperty(self.compass, "enabled", True) post_event.assignProperty(self.exact_angle, "enabled", True) pre_system.addTransition( self.systems.acted, pre_event ) pre_system.addTransition(self.timeout_timer.timeout, pre_system) pre_event.addTransition(self.timeout_timer.timeout, pre_system) post_event.addTransition(self.timeout_timer.timeout, pre_system) pre_event.addTransition( self.systems.acted, pre_event ) post_event.addTransition( self.systems.acted, pre_event ) post_event.addTransition( self.events.acted, post_event ) pre_event.addTransition( self.events.acted, post_event ) pre_system.entered.connect(self.events.switch_active) pre_system.entered.connect(self.systems.switch_active) pre_event.entered.connect(self.events.switch_active) post_event.exited.connect(self.compass.clear_state) post_event.exited.connect(lambda: self.exact_angle.log_angle(False)) self.log_state.setRunning(True)
class MainWindow(QMainWindow): """ This is a class that creates a PyQt5 window containing start, stop, and exit buttons as well as gesture icons. The window is the main window for our program. Attributes: commands: KeyboardCommand class object capture: QtCapture class object camera: OpenCV camera object command_thread: CommandThread class object google_earth: GoogleEarth class object popup_window: QMessageBox object popup_title (string) : Pop up window title popup_text (string) : Pop up window body text desktop : Available screen geometry based on current screen resolution screen : Total screen geometry based on current screen resolution qt_window_height (int) : Calculated value for gesture icon window size layout : Instantiate QVBoxLayout or QHBoxLayout classes, used for aligning images and buttons label_dict (dict) : Contains labels that are used to display gesture icon images image_list (list) : Contains names of image files for gesture icon images title_list (list) : Contains names of titles for corresponding gesture images state_machine: Instantiate QStateMachine class, used to control state of program buttons label : Instantiate QLabel class, labels used to hold gesture icon images and text button : Instantiate QPushButton class, buttons used to start, stop, and exit program widget : Insantiate QWidget class, contains and displays labels and buttons Args: earth : GoogleEarth class object desk_geo: Available screen geometry screen_geo: Total screen geometry """ # Signals for updating state of state machine onSignal = pyqtSignal() offSignal = pyqtSignal() def __init__(self, earth, desk_geo, screen_geo, *args, **kwargs): """ Please see help(MainWindow) for more info. """ super(MainWindow, self).__init__(*args, **kwargs) # Instantiate KeyboardCommands class self.commands = KeyboardCommands() # Will hold hand_recognition QtCapture class self.capture = None # Will hold camera object for OpenCV self.camera = None # Will hold thread for issuing GE commands self.command_thread = None # Make Qt gesture icon window frameless self.setWindowFlags(QtCore.Qt.FramelessWindowHint) # Get resolution, window size, and offsets for positioning self.google_earth = earth # Variables for popup windows self.popup_window = None self.popup_title = "" self.popup_text = "" # Available screen geometry self.desktop = desk_geo # Total screen geometry self.screen = screen_geo # Sets gesture icon window to be 1/4 of available screen space self.qt_window_height = int(self.desktop.height() * 1 / 4) # Set geometry of Qt gesture icon window self.setGeometry( QtWidgets.QStyle.alignedRect( QtCore.Qt.LeftToRight, QtCore.Qt.AlignCenter, QtCore.QSize(self.desktop.width(), self.qt_window_height), self.desktop)) # Create layouts for organizing Qt gesture icon window self.layout = QVBoxLayout() self.layout1 = QHBoxLayout() self.layout2 = QHBoxLayout() self.layout3 = QHBoxLayout() # Dictionary to hold labels once they are created self.label_dict = dict() # Lists hold gesture icon file names and gesture icon titles self.image_list = [ 'images/index_up.png', 'images/v_sign.png', 'images/thumb_left.png', 'images/thumb_right.png', 'images/fist.png', 'images/five_wide.png', 'images/palm.png', 'images/shaka.png' ] self.title_list = [ 'Move Up', 'Move Down', 'Move Left', 'Move Right', 'Zoom In', 'Zoom Out', 'Tilt Up', 'Tilt Down' ] # Create and add 6 labels containing hand gesture image to layout2 and 6 # labels with the gesture descriptions to layout1 for num in range(0, 8): # Each label is created to hold gesture icon image self.label = QLabel(self) # Pixmap is created with the current gesture icon image self.pixmap = QPixmap(self.image_list[num]) # Breakpoints to scale size of gesture icons for different resolutions if self.screen.width() >= 2560: self.pixmap = self.pixmap.scaledToWidth(225) elif self.screen.width() >= 1920: self.pixmap = self.pixmap.scaledToWidth(185) elif self.screen.width() > 1280 and self.screen.height() >= 1200: self.pixmap = self.pixmap.scaledToWidth(175) elif self.screen.width() > 800 and self.screen.height() >= 1024: self.pixmap = self.pixmap.scaledToWidth(125) elif self.screen.width() > 800: self.pixmap = self.pixmap.scaledToWidth(100) else: self.pixmap = self.pixmap.scaledToWidth(50) # Assigns gesture icon image to the current label self.label.setPixmap(self.pixmap) # Create gesture title label for the image self.label_title = QLabel(self.title_list[num]) # Store current icon image label in dictionary self.label_dict[num] = self.label # Place current icon image label in layout self.layout2.addWidget(self.label_dict[num], alignment=QtCore.Qt.AlignCenter) # Place current icon image title label in layout self.layout1.addWidget(self.label_title, alignment=QtCore.Qt.AlignCenter) # Create state machine to reliably handle state changes during threading self.state_machine = QStateMachine() # Create button to handle state changes when pressed self.state_button = QPushButton(self) self.state_button.setStyleSheet("background-color: silver") # Connect button released signal to check_state slot self.state_button.released.connect(self.check_state) # Create on state for state machine self.on = QState() # Create off state for state machine self.off = QState() # Add transition for on state to off state when offSignal is emitted self.on.addTransition(self.offSignal, self.off) # Add transition for on state to on state when state_button clicked signal emitted self.on.addTransition(self.state_button.clicked, self.on) # Add transition for off state to on state when onSignal is emitted self.off.addTransition(self.onSignal, self.on) # Assign text property to state_button in on state self.on.assignProperty(self.state_button, "text", "Start Gesture Navigation") # Assign text property to state_button in off state self.off.assignProperty(self.state_button, "text", "Stop Gesture Navigation") # Add off state to state machine self.state_machine.addState(self.off) # Add on state to state machine self.state_machine.addState(self.on) # Set state machine initial state to on self.state_machine.setInitialState(self.on) # State state machine self.state_machine.start() # Create gesture tips button and connect it to start_gesture_tips slot self.tips_button = QPushButton("Gesture Navigation Tips") self.tips_button.setStyleSheet("background-color: silver") self.tips_button.pressed.connect(self.start_gesture_tips) # Create exit button and connect it to exit slot self.exit_button = QPushButton("Exit Program") self.exit_button.setStyleSheet("background-color: silver") self.exit_button.pressed.connect(self.exit) # Add tips, state, and exit button to layout 3 self.layout3.addWidget(self.tips_button) self.layout3.addWidget(self.state_button) self.layout3.addWidget(self.exit_button) # Add layout 1, 2, and 3 to layout self.layout.addLayout(self.layout1) self.layout.addLayout(self.layout2) self.layout.addLayout(self.layout3) # Create widget to hold layout, add layout to widget self.widget = QWidget() self.widget.setLayout(self.layout) # Set widget with layouts as central widget self.setCentralWidget(self.widget) # Function to display pop up windows and block GUI loop until closed def show_popup(self, title, message, icon): """ Function to create a pop up window that blocks the event loop until it is closed. Used to send info or warning messages. Parameters: title (string) : Title of pop up window message (string) : Body text of pop up window icon : QMessageBox icon to be displayed """ # Create QMessageBox for pop up message self.popup_window = QMessageBox() # Set pop up title to passed in title self.popup_window.setWindowTitle(title) # Set pop up body text to passed in message self.popup_window.setText(message) # Set pop up icon to passed in icon self.popup_window.setIcon(icon) # Set pop up window to use Ok close button self.popup_window.setStandardButtons(QMessageBox.Ok) # Execute pop up window so that it blocks GUI loop until closed self.popup_window.exec() # Check state of state machine, take actions based on current state def check_state(self): """ Function to check the current state of the state machine. Calls check_earth_tips if in on state, calls stop_opencv if in off state. """ current_state = self.state_machine.configuration() if self.on in current_state: self.check_earth_tips() elif self.off in current_state: self.stop_opencv() def start_gesture_tips(self): """ Function to create PyHand Earth gesture navigation tips window. """ # Sets title of pop up window self.popup_title = "Welcome to PyHand Earth!" # Sets body text of pop up window self.popup_text = """\nThis program allows you to navigate the Google Earth Pro desktop application using only your Webcam and eight hand gestures. \n\t Instructions and Tips \n\nFor the best experience, please read the instructions below and then close this window: \n\n1. Position your webcam so that you have a blank, light-colored background behind you. \n\n2. Position your right hand and desired gesture in front of the webcam so that it fills a good portion of the orange bounding rectangle in the live video window once it opens. \n\n3. If the prediction is stuck on the wrong gesture, just shake your hand a little and let it reset. \n\n4. If you remove your hand completely and have a blank background, navigation should halt. \n\n5. Happy navigating! """ # Calls show_popup to create pop up window self.show_popup(self.popup_title, self.popup_text, QMessageBox.Information) def check_earth_tips(self): """ Called by check_state when state machine is in on state. Checks to see if Google Earth Start-up Tips window is open, and asks user to close the window with a pop up window message. If Google Earth Start-up Tips window is closed, calls open_camera. """ # Checks if Google Earth start-up tips window is open if self.google_earth.start_up_tips(): # Sets title of pop up window self.popup_title = "Gesture Navigation Warning Message" # Sets body text of pop up window self.popup_text = "Please make sure the Start-up Tips window is closed before " + \ "starting gesture navigation" # Calls show_popup to create pop up window self.show_popup(self.popup_title, self.popup_text, QMessageBox.Warning) else: # If Google Earth start-up tips window now open, calls open_camera self.open_camera() def open_camera(self): """ Function to create OpenCV VideoCapture object. If camera is not found, creates pop up window message to warn user and ask them to connect a camera. If camera is found, calls start_opencv. """ # Creates cv2 VideoCapture object, passing in -1 to find first active camera self.camera = cv2.VideoCapture(-1) # If camera is not found, create pop up window to warn the user if self.camera is None or not self.camera.isOpened(): # Sets title of pop up window self.popup_title = "No Camera Found Warning Message" # Sets body text of pop up window self.popup_text = "No camera has been detected. \n\nPlease connect a camera before " + \ "starting gesture navigation.\n" # Calls show_popup to create pop up window self.show_popup(self.popup_title, self.popup_text, QMessageBox.Warning) else: # If camera is found, calls start_opencv self.start_opencv() def start_opencv(self): """ Function to start the OpenCV gesture navigation window. Repositions the Google Earth window to take up half of the screen, then calls create_opencv to instantiate QtCapture window. The CommandThread class object is then instantiated to begin sending commands generated in the CaptureThread class to Google Earth. The QtCapture window is then displayed. Finally, the offSignal is emitted to change the state machine to the off state and the tips_button is disabled to prevent tips from being shown while gesture navigation is active. """ # Repositions Google Earth to take up one half of the available screen size self.google_earth.reposition_earth_small() # If opencv window not created, create it if not self.capture: self.create_opencv() else: self.capture = None self.create_opencv() # If command thread exists, remove it if self.command_thread: self.command_thread = None # Start command thread for sending commands to GE self.command_thread = CommandThread(self.capture, self.commands) self.command_thread.start() # Show opencv window self.capture.show() # Emits offSignal to ensure button in correct state self.offSignal.emit() # Disable tips button while gesture navigation is active self.tips_button.setEnabled(False) def create_opencv(self): """ Creates QtCapture window to display the OpenCV window frames. Resizes and repositions the QtCapture window based on current monitor resolution. """ # Create QtCapture window for rendering opencv window self.capture = QtCapture(self.desktop, self.screen, self.camera) self.capture.setParent(self.widget) self.capture.setWindowFlags(QtCore.Qt.Tool) self.capture.setWindowTitle("OpenCV Recording Window") # Get new height based on available screen space minus an offset for the window title new_height = int((self.desktop.height() * 3 / 4) - 35) # Get width that is half of the available screen space half_width = int(self.desktop.width() / 2) # Breakpoints to resize and reposition QtCapture window based on current monitor resolution if self.screen.width() > 1280: window_x = int(self.desktop.width() / 2) + (self.screen.width() - self.desktop.width()) self.capture.setGeometry(window_x, 0, half_width, new_height) elif self.screen.width() > 1152: new_width = int((self.desktop.width() * 29 / 64) + 3) window_x = int(half_width + (half_width - new_width) + (self.screen.width() - self.desktop.width())) self.capture.setGeometry(window_x, 0, new_width, new_height) elif self.screen.width() > 1024: new_width = int((self.desktop.width() * 25 / 64)) window_x = int(half_width + (half_width - new_width) + (self.screen.width() - self.desktop.width())) self.capture.setGeometry(window_x, 0, new_width, new_height) else: new_width = int((self.desktop.width() * 20 / 64) - 3) window_x = int(half_width + (half_width - new_width) + (self.screen.width() - self.desktop.width())) self.capture.setGeometry(window_x, 0, new_width, new_height) def stop_opencv(self): """ Function to close the QtCapture OpenCV window and stop commands being sent to Google Earth. """ # Sends request to end the Google Earth command thread self.command_thread.end_thread() time.sleep(1) # If capture object exists, end thread, release camera, and close window if self.capture: self.capture.stop_thread() time.sleep(1) self.capture.delete() self.capture.setParent(None) # Repositions Google Earth to take up full width of available screen space self.google_earth.reposition_earth_large() # Emits onSignal to ensure button in correct state self.onSignal.emit() # Enable tips when gesture navigation is not active self.tips_button.setEnabled(True) def exit(self): """ Slot function for exit button signal. Stops commands being sent to Google Earth, ends the OpenCV window thread if running, closes Google Earth, and exits the Qt application. """ # If the command thread is running, request thread end if self.command_thread: self.command_thread.end_thread() time.sleep(1) # If the capture thread is running, request thread end if self.capture: self.capture.stop_thread() time.sleep(1) # Close the Google Earth window self.google_earth.close_earth() # Quit the Qt application, returning to main QtCore.QCoreApplication.instance().quit()
class FeedbackDisplay(QStateMachine): """CLASS: FeedbackDisplay This class wraps a QStateMachine and a QLCDNumber in the GUI so it can keep track of a target value and prevent competing display changes. SIGNALS SLOTS --------------------- -------------------- lowerTarget () (float) changeTarget raiseTarget () () sendRequest sendToSerial (str) () sendTarget targetChanged (float) """ targetChanged = pyqtSignal(float) """SIGNAL: targetChanged Emitted when the target value has changed Broadcasts: float - The new target value Connects to: TODO: (probably necessary for FPS) """ raiseTarget = pyqtSignal() """SIGNAL: raiseTarget Internal state change signal Broadcasts: none Connects to: stateMachine transition (* -> upState) """ lowerTarget = pyqtSignal() """SIGNAL: lowerTarget Internal state change signal Broadcasts: none Connects to: stateMachine transition (* -> downState) """ sendToSerial = pyqtSignal(str) """SIGNAL: sendToSerial Delivers a message to be sent over serial Broadcasts: str - The message being sent Connects to: MetroMini.broadcast """ def __init__(self, lcd, targetVal, serial=None, template=None): super().__init__() self.defaultState = DisplayState(lcd, Color.BLACK, 0.0) self.upState = DisplayState(lcd, Color.GREEN) self.downState = DisplayState(lcd, Color.RED) self.waitState = QState() self.setTimer = QTimer() self.setTimer.setInterval(DELAY_BEFORE_SET) self.setTimer.setSingleShot(True) self.waitState.entered.connect(self.setTimer.start) self.waitState.exited.connect(self.setTimer.stop) for s in [ self.defaultState, self.upState, self.downState, self.waitState ]: self.addState(s) s.addTransition(self.raiseTarget, self.upState) s.addTransition(self.lowerTarget, self.downState) for s in [self.upState, self.downState]: s.addTransition(s.done, self.waitState) self.waitState.addTransition(self.setTimer.timeout, self.defaultState) self.setInitialState(self.defaultState) self.target = float(targetVal) if serial is not None: #self.serial = serial self.template = template serial.newDataAvailable.connect(self.defaultState.updateDisplay) self.waitState.exited.connect(self.sendTarget) self.sendToSerial.connect(serial.broadcast) self.requestTimer = QTimer() self.requestTimer.setInterval(REFRESH_PERIOD) self.requestTimer.timeout.connect(self.sendRequest) self.defaultState.entered.connect(self.requestTimer.start) self.defaultState.exited.connect(self.requestTimer.stop) self.start() def getTarget(self): """METHOD: getTarget Access method for the current target value Called by: DisplayState.onEntry Arguments: none Returns: float - The current target value """ return self.target def changeTarget(self, delta): """SLOT: changeTarget Applies a numeric change to the stored target value and directs the QLCDNumber to show that change. Expects: float: The amount by which to shift the target value Connects to: QPushButton.clicked (MainWindow.fpsUpButton, MainWindow.fpsDownButton, MainWindow.psiUpButton, MainWindow.psiDownButton) Emits: raiseTarget, lowerTarget, targetChanged """ self.target += float(delta) if delta > 0: self.raiseTarget.emit() elif delta < 0: self.lowerTarget.emit() self.targetChanged.emit(self.target) def sendRequest(self): """SLOT: sendRequest Sends a serial message requesting a new value from the Metro Mini. Eliminates the need for lambda. Expects: none Connects to: (MainWindow.psiDisplay) QTimer.timeout (requestTimer) Emits: sendToSerial """ self.sendToSerial.emit("request;") def sendTarget(self): """SLOT: sendTarget Sends a serial message with a new target value to the Metro Mini. Eliminates the need for lambda. Expects: none Connects to: (MainWindow.psiDisplay) QState.exited (waitState) Called by: MainWindow.initializeSerialObjects Emits: sendToSerial """ self.sendToSerial.emit(self.template.format(self.target))
class LifeCycle(object): def __init__(self, stickMan, keyReceiver): self.m_stickMan = stickMan self.m_keyReceiver = keyReceiver # Create animation group to be used for all transitions. self.m_animationGroup = QParallelAnimationGroup() stickManNodeCount = self.m_stickMan.nodeCount() self._pas = [] for i in range(stickManNodeCount): pa = QPropertyAnimation(self.m_stickMan.node(i), 'pos') self._pas.append(pa) self.m_animationGroup.addAnimation(pa) # Set up intial state graph. self.m_machine = QStateMachine() self.m_machine.addDefaultAnimation(self.m_animationGroup) self.m_alive = QState(self.m_machine) self.m_alive.setObjectName('alive') # Make it blink when lightning strikes before entering dead animation. lightningBlink = QState(self.m_machine) lightningBlink.assignProperty(self.m_stickMan.scene(), 'backgroundBrush', Qt.white) lightningBlink.assignProperty(self.m_stickMan, 'penColor', Qt.black) lightningBlink.assignProperty(self.m_stickMan, 'fillColor', Qt.white) lightningBlink.assignProperty(self.m_stickMan, 'isDead', True) timer = QTimer(lightningBlink) timer.setSingleShot(True) timer.setInterval(100) lightningBlink.entered.connect(timer.start) lightningBlink.exited.connect(timer.stop) self.m_dead = QState(self.m_machine) self.m_dead.assignProperty(self.m_stickMan.scene(), 'backgroundBrush', Qt.black) self.m_dead.assignProperty(self.m_stickMan, 'penColor', Qt.white) self.m_dead.assignProperty(self.m_stickMan, 'fillColor', Qt.black) self.m_dead.setObjectName('dead') # Idle state (sets no properties). self.m_idle = QState(self.m_alive) self.m_idle.setObjectName('idle') self.m_alive.setInitialState(self.m_idle) # Lightning strikes at random. self.m_alive.addTransition(LightningStrikesTransition(lightningBlink)) lightningBlink.addTransition(timer.timeout, self.m_dead) self.m_machine.setInitialState(self.m_alive) def setDeathAnimation(self, fileName): deathAnimation = self.makeState(self.m_dead, fileName) self.m_dead.setInitialState(deathAnimation) def start(self): self.m_machine.start() def addActivity(self, fileName, key): state = self.makeState(self.m_alive, fileName) self.m_alive.addTransition( KeyPressTransition(self.m_keyReceiver, key, state)) def makeState(self, parentState, animationFileName): topLevel = QState(parentState) animation = Animation() file = QFile(animationFileName) if file.open(QIODevice.ReadOnly): animation.load(file) frameCount = animation.totalFrames() previousState = None for i in range(frameCount): animation.setCurrentFrame(i) frameState = QState(topLevel) nodeCount = animation.nodeCount() for j in range(nodeCount): frameState.assignProperty(self.m_stickMan.node(j), 'pos', animation.nodePos(j)) frameState.setObjectName('frame %d' % i) if previousState is None: topLevel.setInitialState(frameState) else: previousState.addTransition(previousState.propertiesAssigned, frameState) previousState = frameState previousState.addTransition(previousState.propertiesAssigned, topLevel.initialState()) return topLevel
class NS_Animate(object): def __init__(self, scene, x_max, y_max, back_color): scene = QGraphicsScene(0, 0, x_max, y_max) scene.setBackgroundBrush(back_color) color = [Qt.green, Qt.lightGray, Qt.darkYellow, QtGui.QColor.fromRgb(255, 85, 0)] self.anim_butt = [ QGraphicsRectWidget(color[j]) for j in range(4) ] for j in range(4): scene.addItem(self.anim_butt[j]) self.window = QGraphicsView(scene) self.window.setFrameStyle(0) self.window.setAlignment(Qt.AlignLeft | Qt.AlignTop) self.window.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.window.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.machine = QStateMachine() self.group = QState() self.timer = QTimer() self.timer.setInterval(1250) self.timer.setSingleShot(True) self.group.entered.connect(self.timer.start) # set states positions anim_state_rects = [ [QRect(x_max*xp/6, y_max*yp/4, 8, 8) for xp in range(4)] for yp in range(4) ] self.states = [ self.createGeometryState( self.anim_butt[0], anim_state_rects[0][j], self.anim_butt[1], anim_state_rects[1][j], self.anim_butt[2], anim_state_rects[2][j], self.anim_butt[3], anim_state_rects[3][j], self.group ) for j in range(4) ] self.group.setInitialState(self.states[0]) self.animationGroup = QParallelAnimationGroup() self.anim = QPropertyAnimation(self.anim_butt[3], 'geometry') self.anim.setDuration(1250) self.anim.setEasingCurve(QEasingCurve.InBack) self.animationGroup.addAnimation(self.anim) self.subGroup = QSequentialAnimationGroup(self.animationGroup) self.subGroup.addPause(100) self.anim = QPropertyAnimation(self.anim_butt[2], 'geometry') self.anim.setDuration(1000) self.anim.setEasingCurve(QEasingCurve.OutElastic) self.subGroup.addAnimation(self.anim) self.subGroup = QSequentialAnimationGroup(self.animationGroup) self.subGroup.addPause(500) self.anim = QPropertyAnimation(self.anim_butt[1], 'geometry') self.anim.setDuration(500) self.anim.setEasingCurve(QEasingCurve.OutElastic) self.subGroup.addAnimation(self.anim) self.subGroup = QSequentialAnimationGroup(self.animationGroup) self.subGroup.addPause(750) self.anim = QPropertyAnimation(self.anim_butt[0], 'geometry') self.anim.setDuration(250) self.anim.setEasingCurve(QEasingCurve.OutElastic) self.subGroup.addAnimation(self.anim) self.stateSwitcher = StateSwitcher(self.machine) self.group.addTransition(self.timer.timeout, self.stateSwitcher) for j in range(4): self.stateSwitcher.addState(self.states[j], self.animationGroup) self.machine.addState(self.group) self.machine.setInitialState(self.group) self.machine.start() # def createGeometryState(self, w1, rect1, w2, rect2, w3, rect3, w4, rect4, parent): result = QState(parent) result.assignProperty(w1, 'geometry', rect1) result.assignProperty(w1, 'geometry', rect1) result.assignProperty(w2, 'geometry', rect2) result.assignProperty(w3, 'geometry', rect3) result.assignProperty(w4, 'geometry', rect4) return result
class LifeCycle(object): def __init__(self, stickMan, keyReceiver): self.m_stickMan = stickMan self.m_keyReceiver = keyReceiver # Create animation group to be used for all transitions. self.m_animationGroup = QParallelAnimationGroup() stickManNodeCount = self.m_stickMan.nodeCount() self._pas = [] for i in range(stickManNodeCount): pa = QPropertyAnimation(self.m_stickMan.node(i), b"pos") self._pas.append(pa) self.m_animationGroup.addAnimation(pa) # Set up intial state graph. self.m_machine = QStateMachine() self.m_machine.addDefaultAnimation(self.m_animationGroup) self.m_alive = QState(self.m_machine) self.m_alive.setObjectName("alive") # Make it blink when lightning strikes before entering dead animation. lightningBlink = QState(self.m_machine) lightningBlink.assignProperty(self.m_stickMan.scene(), "backgroundBrush", Qt.white) lightningBlink.assignProperty(self.m_stickMan, "penColor", Qt.black) lightningBlink.assignProperty(self.m_stickMan, "fillColor", Qt.white) lightningBlink.assignProperty(self.m_stickMan, "isDead", True) timer = QTimer(lightningBlink) timer.setSingleShot(True) timer.setInterval(100) lightningBlink.entered.connect(timer.start) lightningBlink.exited.connect(timer.stop) self.m_dead = QState(self.m_machine) self.m_dead.assignProperty(self.m_stickMan.scene(), "backgroundBrush", Qt.black) self.m_dead.assignProperty(self.m_stickMan, "penColor", Qt.white) self.m_dead.assignProperty(self.m_stickMan, "fillColor", Qt.black) self.m_dead.setObjectName("dead") # Idle state (sets no properties). self.m_idle = QState(self.m_alive) self.m_idle.setObjectName("idle") self.m_alive.setInitialState(self.m_idle) # Lightning strikes at random. self.m_alive.addTransition(LightningStrikesTransition(lightningBlink)) lightningBlink.addTransition(timer.timeout, self.m_dead) self.m_machine.setInitialState(self.m_alive) def setDeathAnimation(self, fileName): deathAnimation = self.makeState(self.m_dead, fileName) self.m_dead.setInitialState(deathAnimation) def start(self): self.m_machine.start() def addActivity(self, fileName, key): state = self.makeState(self.m_alive, fileName) self.m_alive.addTransition(KeyPressTransition(self.m_keyReceiver, key, state)) def makeState(self, parentState, animationFileName): topLevel = QState(parentState) animation = Animation() file = QFile(animationFileName) if file.open(QIODevice.ReadOnly): animation.load(file) frameCount = animation.totalFrames() previousState = None for i in range(frameCount): animation.setCurrentFrame(i) frameState = QState(topLevel) nodeCount = animation.nodeCount() for j in range(nodeCount): frameState.assignProperty(self.m_stickMan.node(j), "pos", animation.nodePos(j)) frameState.setObjectName("frame %d" % i) if previousState is None: topLevel.setInitialState(frameState) else: previousState.addTransition(previousState.propertiesAssigned, frameState) previousState = frameState previousState.addTransition(previousState.propertiesAssigned, topLevel.initialState()) return topLevel
subGroup = QSequentialAnimationGroup(animationGroup) subGroup.addPause(150) anim = QPropertyAnimation(button2, 'geometry') anim.setDuration(1000) anim.setEasingCurve(QEasingCurve.OutElastic) subGroup.addAnimation(anim) subGroup = QSequentialAnimationGroup(animationGroup) subGroup.addPause(200) anim = QPropertyAnimation(button1, 'geometry') anim.setDuration(1000) anim.setEasingCurve(QEasingCurve.OutElastic) subGroup.addAnimation(anim) stateSwitcher = StateSwitcher(machine) group.addTransition(timer.timeout, stateSwitcher) stateSwitcher.addState(state1, animationGroup) stateSwitcher.addState(state2, animationGroup) stateSwitcher.addState(state3, animationGroup) stateSwitcher.addState(state4, animationGroup) stateSwitcher.addState(state5, animationGroup) stateSwitcher.addState(state6, animationGroup) stateSwitcher.addState(state7, animationGroup) machine.addState(group) machine.setInitialState(group) machine.start() window.resize(300, 300) window.show()
view.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) view.show() states = QStateMachine() states.addState(rootState) states.setInitialState(rootState) rootState.setInitialState(centeredState) group = QParallelAnimationGroup() for i, item in enumerate(items): anim = QPropertyAnimation(item, b'pos') anim.setDuration(750 + i * 25) anim.setEasingCurve(QEasingCurve.InOutBack) group.addAnimation(anim) trans = rootState.addTransition(ellipseButton.pressed, ellipseState) trans.addAnimation(group) trans = rootState.addTransition(figure8Button.pressed, figure8State) trans.addAnimation(group) trans = rootState.addTransition(randomButton.pressed, randomState) trans.addAnimation(group) trans = rootState.addTransition(tiledButton.pressed, tiledState) trans.addAnimation(group) trans = rootState.addTransition(centeredButton.pressed, centeredState) trans.addAnimation(group) timer = QTimer()
#tr = QScxmlSignalTransition(pb.clicked) scxml_machine = QScxml() scxml_machine.registerObject(pb, "pb") scxml_machine.registerObject(cb, "cb") scxml_machine.load("test144.scxml") #scxml_machine = QScxml.load("ExifMediaRename.scxml", ) scxml_machine.start() if 0: sm = QStateMachine() s1 = QState() s2 = QState() s2.entered.connect(toto) st = QSignalTransition(pb.clicked) st.setTargetState(s2) s1.addTransition(st) sm.addState(s1) sm.addState(s2) sm.setInitialState(s1) sm.start() sys.exit(app.exec_())
subGroup = QSequentialAnimationGroup(animationGroup) subGroup.addPause(150) anim = QPropertyAnimation(button2, 'geometry') anim.setDuration(1000) anim.setEasingCurve(QEasingCurve.OutElastic) subGroup.addAnimation(anim) subGroup = QSequentialAnimationGroup(animationGroup) subGroup.addPause(200) anim = QPropertyAnimation(button1, 'geometry') anim.setDuration(1000) anim.setEasingCurve(QEasingCurve.OutElastic) subGroup.addAnimation(anim) stateSwitcher = StateSwitcher(machine) group.addTransition(timer.timeout, stateSwitcher) stateSwitcher.addState(state1, animationGroup) stateSwitcher.addState(state2, animationGroup) stateSwitcher.addState(state3, animationGroup) stateSwitcher.addState(state4, animationGroup) stateSwitcher.addState(state5, animationGroup) stateSwitcher.addState(state6, animationGroup) stateSwitcher.addState(state7, animationGroup) machine.addState(group) machine.setInitialState(group) machine.start() window.resize(300, 300) window.show()
state3.assignProperty(p1, 'pos', QPointF(0, 5)) state3.assignProperty(p2, 'pos', QPointF(0, 5 + 64 + 5)) state3.assignProperty(p3, 'pos', QPointF(5, 5 + (64 + 5) + 64)) state3.assignProperty(p4, 'pos', QPointF(5 + 64 + 5, 5)) state3.assignProperty(p5, 'pos', QPointF(5 + 64 + 5, 5 + 64 + 5)) state3.assignProperty(p6, 'pos', QPointF(5 + 64 + 5, 5 + (64 + 5) + 64)) state3.assignProperty(widget, 'geometry', QRectF(138, 5, 400 - 138, 200)) state3.assignProperty(box, 'geometry', QRect(5, 205, 400, 90)) state3.assignProperty(p1, 'opacity', 1.0) state3.assignProperty(p2, 'opacity', 1.0) state3.assignProperty(p3, 'opacity', 1.0) state3.assignProperty(p4, 'opacity', 1.0) state3.assignProperty(p5, 'opacity', 1.0) state3.assignProperty(p6, 'opacity', 1.0) t1 = state1.addTransition(button.clicked, state2) animation1SubGroup = QSequentialAnimationGroup() animation1SubGroup.addPause(250) animation1SubGroup.addAnimation( QPropertyAnimation(box, b'geometry', state1)) t1.addAnimation(animation1SubGroup) t1.addAnimation(QPropertyAnimation(widget, b'geometry', state1)) t1.addAnimation(QPropertyAnimation(p1, b'pos', state1)) t1.addAnimation(QPropertyAnimation(p2, b'pos', state1)) t1.addAnimation(QPropertyAnimation(p3, b'pos', state1)) t1.addAnimation(QPropertyAnimation(p4, b'pos', state1)) t1.addAnimation(QPropertyAnimation(p5, b'pos', state1)) t1.addAnimation(QPropertyAnimation(p6, b'pos', state1)) t1.addAnimation(QPropertyAnimation(p1, b'rotation', state1)) t1.addAnimation(QPropertyAnimation(p2, b'rotation', state1)) t1.addAnimation(QPropertyAnimation(p3, b'rotation', state1))
class QKeithleySolar(QVisaApplication.QVisaApplication): def __init__(self, _config): # Inherits QVisaApplication -> QWidget super(QKeithleySolar, self).__init__(_config) # Generate Main Layout self.gen_main_layout() ##################################### # APPLICATION HELPER METHODS # # Wrapper method to get keitley write handle # Returns the pyVisaDevice object def keithley(self): return self.get_device_by_name(self.device_select.currentText()) # Update bias on keithley def update_bias(self, _value): if self.keithley() is not None: self.keithley().set_voltage(_value) # Method to refresh the widget def refresh(self): # If add insturments have been initialized if self.get_devices() is not None: # Reset the widget and add insturments self.device_select.refresh(self) # Enable measurement buttons self.iv_meas_button.setEnabled(True) self.voc_meas_button.setEnabled(True) self.mpp_meas_button.setEnabled(True) else: # Disable measurement buttons self.iv_meas_button.setEnabled(False) self.voc_meas_button.setEnabled(False) self.mpp_meas_button.setEnabled(False) ##################################### # SOLAR APP MAIN LAYOUTS # # *) gen_main_layout() # 1) gen_solar_ctrl() # a) gen_sweep_ctrl() # b) gen_voc_ctrl() # c) gen_mpp_crtl() # 2) gen_solar_plot() # def gen_main_layout(self): # Create Icon for QMessageBox self._set_icon( QIcon( os.path.join(os.path.dirname(os.path.realpath(__file__)), "python.ico"))) # Create layout objects and set layout self.layout = QHBoxLayout() self.layout.addLayout(self.gen_solar_ctrl(), 1) self.layout.addWidget(self.gen_solar_plot(), 3) self.setLayout(self.layout) # Method to generate solar characterization controls def gen_solar_ctrl(self): # Solar mode layout self.ctl_layout = QVBoxLayout() # Add insturement selector self.device_select_label = QLabel("Select Device") self.device_select = self._gen_device_select() self.device_select.setFixedWidth(200) # Generate (IV, Voc, MPP) container widgets # These methods will pack self.inst_select self.gen_iv_ctrl() # self.iv_ctrl self.gen_voc_ctrl() # self.voc_ctrl self.gen_mpp_ctrl() # self.mpp_ctrl # Add measurement widgets to QStackedWidget self.meas_pages = QStackedWidget() self.meas_pages.addWidget(self.iv_ctrl) self.meas_pages.addWidget(self.voc_ctrl) self.meas_pages.addWidget(self.mpp_ctrl) self.meas_pages.setCurrentIndex(0) # Measurement select QComboBox self.meas_select_label = QLabel("Measurement Mode") self.meas_select = QComboBox() self.meas_select.setFixedWidth(200) self.meas_select.addItems(["IV", "Voc", "MPP"]) self.meas_select.currentTextChanged.connect(self.update_meas_pages) # Meta widget for trace description self.meta_widget_label = QLabel("<b>Trace Description</b>") self.meta_widget = self._gen_meta_widget() self.meta_widget.set_meta_subkey("__desc__") self.save_widget = self._gen_save_widget() ##################################### # ADD CONTROLS # # Add measurement select and measurement pages self.ctl_layout.addWidget(self.meas_pages) self.ctl_layout.addWidget( self._gen_hbox_widget([self.meas_select, self.meas_select_label])) self.ctl_layout.addWidget( self._gen_hbox_widget( [self.device_select, self.device_select_label])) # Pack the standard save widget self.ctl_layout.addStretch(1) self.ctl_layout.addWidget(self.meta_widget_label) self.ctl_layout.addWidget(self.meta_widget) self.ctl_layout.addWidget(self.save_widget) # Positioning self.ctl_layout.setContentsMargins(0, 15, 0, 20) return self.ctl_layout ##################################### # MEASUREMENT MODE CONTROLS # # Method to generate sweep controls def gen_iv_ctrl(self): # Sweep control layout self.iv_ctrl = QWidget() self.iv_ctrl_layout = QVBoxLayout() # Sweep measurement Button. This will be a state machine which # alternates between 'measure' and 'abort' states self.iv_meas_state = QStateMachine() self.iv_meas_button = QPushButton() self.iv_meas_button.setStyleSheet( "background-color: #dddddd; border-style: solid; border-width: 1px; border-color: #aaaaaa; padding: 7px;" ) # Create measurement states self.iv_meas_run = QState() self.iv_meas_stop = QState() # Assign state properties and transitions self.iv_meas_run.assignProperty(self.iv_meas_button, 'text', 'Abort Sweep') self.iv_meas_run.addTransition(self.iv_meas_button.clicked, self.iv_meas_stop) self.iv_meas_run.entered.connect(self.exec_iv_run) self.iv_meas_stop.assignProperty(self.iv_meas_button, 'text', 'Measure Sweep') self.iv_meas_stop.addTransition(self.iv_meas_button.clicked, self.iv_meas_run) self.iv_meas_stop.entered.connect(self.exec_iv_stop) # Add states, set initial state, and state machine self.iv_meas_state.addState(self.iv_meas_run) self.iv_meas_state.addState(self.iv_meas_stop) self.iv_meas_state.setInitialState(self.iv_meas_stop) self.iv_meas_state.start() # Sweep start self.iv_start_config = { "unit": "V", "min": "m", "max": "", "label": "Sweep Start (V)", "limit": 2.0, "signed": True, "default": [-0.5, ""] } self.iv_start = QVisaUnitSelector.QVisaUnitSelector( self.iv_start_config) # Sweep stop self.iv_stop_config = { "unit": "V", "min": "m", "max": "", "label": "Sweep Stop (V)", "limit": 2.0, "signed": True, "default": [0.5, ""] } self.iv_stop = QVisaUnitSelector.QVisaUnitSelector(self.iv_stop_config) # Compliance Spinbox self.iv_cmpl_config = { "unit": "A", "min": "u", "max": "", "label": "Compliance (A)", "limit": 1.0, "signed": False, "default": [100, "m"] } self.iv_cmpl = QVisaUnitSelector.QVisaUnitSelector(self.iv_cmpl_config) # Compliance self.iv_npts_config = { "unit": "__INT__", "label": "Number of Points", "limit": 256.0, "signed": False, "default": [51.0] } self.iv_npts = QVisaUnitSelector.QVisaUnitSelector(self.iv_npts_config) # Add sweep widgets to layout self.iv_ctrl_layout.addWidget(self.iv_meas_button) self.iv_ctrl_layout.addWidget(self.iv_start) self.iv_ctrl_layout.addWidget(self.iv_stop) self.iv_ctrl_layout.addWidget(self.iv_cmpl) self.iv_ctrl_layout.addWidget(self.iv_npts) self.iv_ctrl_layout.setContentsMargins(0, 0, 0, 0) # Set widget layout self.iv_ctrl.setLayout(self.iv_ctrl_layout) # Method to generate Voc controls def gen_voc_ctrl(self): # Voc control layout self.voc_ctrl = QWidget() self.voc_ctrl_layout = QVBoxLayout() # Create QStateMachine for output state self.voc_state = QStateMachine() self.voc_meas_button = QPushButton() self.voc_meas_button.setStyleSheet( "background-color: #dddddd; border-style: solid; border-width: 1px; border-color: #aaaaaa; padding: 7px;" ) # Create output states self.voc_meas_off = QState() self.voc_meas_on = QState() # Attach states to output button and define state transitions self.voc_meas_off.assignProperty(self.voc_meas_button, 'text', 'Voc Monitor Off') self.voc_meas_off.addTransition(self.voc_meas_button.clicked, self.voc_meas_on) self.voc_meas_off.entered.connect(self.exec_voc_stop) self.voc_meas_on.assignProperty(self.voc_meas_button, 'text', 'Voc Monitor On') self.voc_meas_on.addTransition(self.voc_meas_button.clicked, self.voc_meas_off) self.voc_meas_on.entered.connect(self.exec_voc_run) # Add states, set initial state, and start machine self.voc_state.addState(self.voc_meas_off) self.voc_state.addState(self.voc_meas_on) self.voc_state.setInitialState(self.voc_meas_off) self.voc_state.start() # Tracking mode initialization # Note this example of passing arguments to a callback self.voc_bias_config = { "unit": "V", "min": "m", "max": "", "label": "Voc Initialization (V)", "limit": 2.0, "signed": True, "default": [0.3, ""] } self.voc_bias = QVisaUnitSelector.QVisaUnitSelector( self.voc_bias_config) self.voc_bias.unit_value.valueChanged.connect( lambda arg=self.voc_bias.value(): self.update_bias(arg)) # Compliance Spinbox self.voc_cmpl_config = { "unit": "A", "min": "u", "max": "", "label": "Compliance (A)", "limit": 1.0, "signed": False, "default": [100, "m"] } self.voc_cmpl = QVisaUnitSelector.QVisaUnitSelector( self.voc_cmpl_config) # Tracking mode convergence self.voc_conv_config = { "unit": "A", "min": "n", "max": "m", "label": "Voc Convergence (A)", "limit": 0.05, "signed": False, "default": [0.05, "u"] } self.voc_conv = QVisaUnitSelector.QVisaUnitSelector( self.voc_conv_config) # Delay self.voc_gain_config = { "unit": "__DOUBLE__", "label": html.unescape("Proportional Gain (‰)"), "limit": 1000, "signed": False, "default": [30.0] } self.voc_gain = QVisaUnitSelector.QVisaUnitSelector( self.voc_gain_config) # Delay self.voc_delay_config = { "unit": "__DOUBLE__", "label": "Measurement Interval (s)", "limit": 60.0, "signed": False, "default": [1.0] } self.voc_delay = QVisaUnitSelector.QVisaUnitSelector( self.voc_delay_config) # Add voc widgets to layout self.voc_ctrl_layout.addWidget(self.voc_meas_button) self.voc_ctrl_layout.addWidget(self.voc_bias) self.voc_ctrl_layout.addWidget(self.voc_cmpl) self.voc_ctrl_layout.addWidget(self.voc_conv) self.voc_ctrl_layout.addWidget(self.voc_gain) self.voc_ctrl_layout.addWidget(self.voc_delay) self.voc_ctrl_layout.setContentsMargins(0, 0, 0, 0) # Set widget layout self.voc_ctrl.setLayout(self.voc_ctrl_layout) # Method to generate MPP controls def gen_mpp_ctrl(self): ################################# # mpp tracking controls # self.mpp_ctrl = QWidget() self.mpp_ctrl_layout = QVBoxLayout() # Create QStateMachine for output state self.mpp_state = QStateMachine() self.mpp_meas_button = QPushButton() self.mpp_meas_button.setStyleSheet( "background-color: #dddddd; border-style: solid; border-width: 1px; border-color: #aaaaaa; padding: 7px;" ) # Create output states self.mpp_meas_off = QState() self.mpp_meas_on = QState() # Attach states to output button and define state transitions self.mpp_meas_off.assignProperty(self.mpp_meas_button, 'text', 'MPP Monitor Off') self.mpp_meas_off.addTransition(self.mpp_meas_button.clicked, self.mpp_meas_on) self.mpp_meas_off.entered.connect(self.exec_mpp_stop) self.mpp_meas_on.assignProperty(self.mpp_meas_button, 'text', 'MPP Monitor On') self.mpp_meas_on.addTransition(self.mpp_meas_button.clicked, self.mpp_meas_off) self.mpp_meas_on.entered.connect(self.exec_mpp_run) # Add states, set initial state, and start machine self.mpp_state.addState(self.mpp_meas_off) self.mpp_state.addState(self.mpp_meas_on) self.mpp_state.setInitialState(self.mpp_meas_off) self.mpp_state.start() # Tracking mode initialization # Note this example of passing arguments to a callback self.mpp_bias_config = { "unit": "V", "min": "m", "max": "", "label": "MPP Initialization (V)", "limit": 2.0, "signed": True, "default": [0.30, ""] } self.mpp_bias = QVisaUnitSelector.QVisaUnitSelector( self.mpp_bias_config) self.mpp_bias.unit_value.valueChanged.connect( lambda arg=self.mpp_bias.value(): self.update_bias(arg)) # Compliance Spinbox self.mpp_cmpl_config = { "unit": "A", "min": "u", "max": "", "label": "Compliance (A)", "limit": 1.0, "signed": False, "default": [100, "m"] } self.mpp_cmpl = QVisaUnitSelector.QVisaUnitSelector( self.mpp_cmpl_config) # Tracking mode convergence self.mpp_ampl_config = { "unit": "V", "min": "u", "max": "m", "label": "Sense amplitude (mV)", "limit": 100, "signed": False, "default": [20.0, "m"] } self.mpp_ampl = QVisaUnitSelector.QVisaUnitSelector( self.mpp_ampl_config) # Delay self.mpp_gain_config = { "unit": "__DOUBLE__", "label": html.unescape("Proportional Gain (‰)"), "limit": 1000, "signed": False, "default": [30.0] } self.mpp_gain = QVisaUnitSelector.QVisaUnitSelector( self.mpp_gain_config) # Delay self.mpp_delay_config = { "unit": "__DOUBLE__", "label": "Measurement Interval (s)", "limit": 60.0, "signed": False, "default": [0.1] } self.mpp_delay = QVisaUnitSelector.QVisaUnitSelector( self.mpp_delay_config) # Add mpp widgets to layout self.mpp_ctrl_layout.addWidget(self.mpp_meas_button) self.mpp_ctrl_layout.addWidget(self.mpp_bias) self.mpp_ctrl_layout.addWidget(self.mpp_cmpl) self.mpp_ctrl_layout.addWidget(self.mpp_ampl) self.mpp_ctrl_layout.addWidget(self.mpp_gain) self.mpp_ctrl_layout.addWidget(self.mpp_delay) self.mpp_ctrl_layout.setContentsMargins(0, 0, 0, 0) # Set widget layout self.mpp_ctrl.setLayout(self.mpp_ctrl_layout) # Method to generate solar cell plots. This will be implemented # as three QVisaDynamicPlots packed into a QStackedWidget def gen_solar_plot(self): # Call QStackedWidget constructor self.plot_stack = QStackedWidget() # Plot IV-Sweep mode self.iv_plot = QVisaDynamicPlot.QVisaDynamicPlot(self) self.iv_plot.add_subplot(111, twinx=True) self.iv_plot.set_axes_labels("111", "Voltage (V)", "Current (mA)") self.iv_plot.set_axes_labels("111t", "Voltage (V)", "Power (mW)") self.iv_plot.set_axes_adjust(_left=0.15, _right=0.85, _top=0.9, _bottom=0.1) self.iv_plot.refresh_canvas(supress_warning=True) self.voc_plot = QVisaDynamicPlot.QVisaDynamicPlot(self) self.voc_plot.add_subplot(111, twinx=True) self.voc_plot.set_axes_labels("111", "Time (s)", "Voc (V)") self.voc_plot.set_axes_labels("111t", "Time (s)", "Ioc (V)") self.voc_plot.set_axes_adjust(_left=0.15, _right=0.85, _top=0.9, _bottom=0.1) self.voc_plot.refresh_canvas(supress_warning=True) self.mpp_plot = QVisaDynamicPlot.QVisaDynamicPlot(self) self.mpp_plot.add_subplot(111, twinx=True) self.mpp_plot.set_axes_labels("111", "Time (s)", "Vmpp (V)") self.mpp_plot.set_axes_labels("111t", "Time (s)", "Pmpp (mW)") self.mpp_plot.set_axes_adjust(_left=0.15, _right=0.85, _top=0.9, _bottom=0.1) self.mpp_plot.refresh_canvas(supress_warning=True) # Sync plot clear data buttons with application data self.iv_plot.sync_application_data(True) self.voc_plot.sync_application_data(True) self.mpp_plot.sync_application_data(True) # Sync meta widget when clearing data from plots self.iv_plot.set_mpl_refresh_callback( "_sync_meta_widget_to_data_object") self.voc_plot.set_mpl_refresh_callback( "_sync_meta_widget_to_data_object") self.mpp_plot.set_mpl_refresh_callback( "_sync_meta_widget_to_data_object") # Add QVisaDynamicPlots to QStackedWidget self.plot_stack.addWidget(self.iv_plot) self.plot_stack.addWidget(self.voc_plot) self.plot_stack.addWidget(self.mpp_plot) # Return the stacked widget self.plot_stack.setCurrentIndex(0) return self.plot_stack # Sync meta widget to data object def _sync_meta_widget_to_data_object(self): # Application keys _data_keys = self._get_data_object().keys() _widget_keys = self.meta_widget.get_meta_keys() # Check if widget keys are not in data keys for _key in _widget_keys: # If not then delete the key from meta_widget if _key not in _data_keys: self.meta_widget.del_meta_key(_key) # Flip between controls when measurement mode selector is updated def update_meas_pages(self): if self.meas_select.currentText() == "IV": self.meas_pages.setCurrentIndex(0) self.plot_stack.setCurrentIndex(0) if self.meas_select.currentText() == "Voc": self.meas_pages.setCurrentIndex(1) self.plot_stack.setCurrentIndex(1) if self.meas_select.currentText() == "MPP": self.meas_pages.setCurrentIndex(2) self.plot_stack.setCurrentIndex(2) # Callback method to delete data when traces are cleared def sync_mpl_clear(self): # Extract plot and data object _plot = self.plot_stack.currentWidget() _data = self._get_data_object() # Note that plot subkeys map to data keys for _subkey in _plot.get_axes_handles().subkeys("111"): _data.del_key(_subkey) ##################################### # IV-SWEEP MEASUREMENT MODE # # Sweep measurement EXECUTION def exec_iv_thread(self): # Set sweep parameters as simple linspace _params = np.linspace(float(self.iv_start.value()), float(self.iv_stop.value()), int(self.iv_npts.value())) # Get QVisaDataObject data = self._get_data_object() key = data.add_hash_key("pv-bias") # Add data fields to key data.set_subkeys(key, ["t", "V", "I", "P"]) data.set_metadata(key, "__type__", "pv-bias") # Add key to meta widget self.meta_widget.add_meta_key(key) # Generate colors _c0 = self.iv_plot.gen_next_color() _c1 = self.iv_plot.gen_next_color() # Clear plot and zero arrays self.iv_plot.add_axes_handle('111', key, _color=_c0) self.iv_plot.add_axes_handle('111t', key, _color=_c1) # Thread start time start = float(time.time()) # Output on self.keithley().voltage_src() self.keithley().current_cmp(self.iv_cmpl.value()) self.keithley().output_on() # Loop through sweep parameters for _bias in _params: # If thread is running if self.iv_thread_running: # Set bias self.keithley().set_voltage(_bias) # Get data from buffer _buffer = self.keithley().meas().split(",") # Extract data from buffer _now = float(time.time() - start) # Append measured values to data arrays data.append_subkey_data(key, "t", _now) data.append_subkey_data(key, "V", float(_buffer[0])) data.append_subkey_data(key, "I", -1.0 * float(_buffer[1])) data.append_subkey_data( key, "P", -1.0 * float(_buffer[1]) * float(_buffer[0])) self.iv_plot.append_handle_data("111", key, float(_buffer[0]), -1.0 * float(_buffer[1])) self.iv_plot.append_handle_data( "111t", key, float(_buffer[0]), -1.0 * float(_buffer[0]) * float(_buffer[1])) self.iv_plot.update_canvas() self.keithley().set_voltage(0.0) self.keithley().output_off() # Reset sweep control and update measurement state to stop. # Post a button click event to the QStateMachine to trigger # a state transition if thread is still running (not aborted) if self.iv_thread_running: self.iv_meas_button.click() # Sweep measurement ON def exec_iv_run(self): if self.keithley() is not None: # Put measurement button in abort state self.iv_meas_button.setStyleSheet( "background-color: #ffcccc; border-style: solid; border-width: 1px; border-color: #800000; padding: 7px;" ) # Disable controls self.save_widget.setEnabled(False) self.device_select.setEnabled(False) self.meas_select.setEnabled(False) self.iv_plot.mpl_refresh_setEnabled(False) self.voc_plot.mpl_refresh_setEnabled(False) self.mpp_plot.mpl_refresh_setEnabled(False) # Run the measurement thread function self.iv_thread = threading.Thread(target=self.exec_iv_thread, args=()) self.iv_thread.daemon = True # Daemonize thread self.iv_thread.start() # Start the execution self.iv_thread_running = True # Sweep measurement OFF def exec_iv_stop(self): if self.keithley() is not None: # Put measurement button in measure state self.iv_meas_button.setStyleSheet( "background-color: #dddddd; border-style: solid; border-width: 1px; border-color: #aaaaaa; padding: 7px;" ) # Enable controls self.save_widget.setEnabled(True) self.device_select.setEnabled(True) self.meas_select.setEnabled(True) self.iv_plot.mpl_refresh_setEnabled(True) self.voc_plot.mpl_refresh_setEnabled(True) self.mpp_plot.mpl_refresh_setEnabled(True) # Set thread running to False. This will break the sweep measurements # execution loop on next iteration. self.iv_thread_running = False self.iv_thread.join() # Waits for thread to complete ##################################### # VOC-MONITOR MEASUREMENT MODE # def exec_voc_thread(self): # Get QVisaDataObject data = self._get_data_object() key = data.add_hash_key("pv-voc") # Add data fields to key data.set_subkeys(key, ["t", "Voc", "Ioc"]) data.set_metadata(key, "__type__", "pv-voc") # Add key to meta widget self.meta_widget.add_meta_key(key) # Generate colors _c0 = self.voc_plot.gen_next_color() _c1 = self.voc_plot.gen_next_color() # Clear plot and zero arrays self.voc_plot.add_axes_handle('111', key, _color=_c0) self.voc_plot.add_axes_handle('111t', key, _color=_c1) # Thread start time start = float(time.time()) # Set bias to initial value in voltas and turn output ON self.keithley().set_voltage(self.voc_bias.value()) self.keithley().current_cmp(self.voc_cmpl.value()) self.keithley().output_on() # Thread loop while self.voc_thread_running is True: # Iteration timer _iter_start = float(time.time()) # Covvergence loop while True: # Get data from buffer _buffer = self.keithley().meas().split(",") # Check if current is below convergence value # note that convergence is specified in mA if (abs(float(_buffer[1]))) <= float(self.voc_conv.value()): break # If convergence takes too long paint a value (10s) elif float(time.time() - _iter_start) >= 3.0: break # Otherwise, adjust the voltage proportionally else: # Create 1mV sense amplitude _v, _i = np.add(float(_buffer[0]), np.linspace(-0.0005, 0.0005, 3)), [] # Measure current over sense amplitude array for _ in _v: self.keithley().set_voltage(_) _b = self.keithley().meas().split(",") _i.append(-1.0 * float(_b[1])) # Reset the voltage self.keithley().set_voltage(float(_buffer[0])) # Adjust bias in direction of lower current # If current is positive (photo-current) increase voltage if np.mean(_i) >= 0.0: self.update_bias( float(_buffer[0]) * float(1.0 + self.voc_gain.value() / 1000.)) else: self.update_bias( float(_buffer[0]) * float(1.0 - self.voc_gain.value() / 1000.)) # Extract data from buffer _now = float(time.time() - start) data.append_subkey_data(key, "t", _now) data.append_subkey_data(key, "Voc", 1.0 * float(_buffer[0])) data.append_subkey_data(key, "Ioc", -1.0 * float(_buffer[1])) # Sanity check # Append handle data and update canvas self.voc_plot.append_handle_data("111", key, _now, 1.0 * float(_buffer[0])) self.voc_plot.append_handle_data("111t", key, _now, -1.0 * float(_buffer[1])) self.voc_plot.update_canvas() # Measurement delay if self.voc_delay.value() != 0: time.sleep(self.voc_delay.value()) # Cleanup after thread termination self.keithley().set_voltage(0.0) self.keithley().output_off() # Tracking measurement ON def exec_voc_run(self): if self.keithley() is not None: # Update UI for ON state self.voc_meas_button.setStyleSheet( "background-color: #cce6ff; border-style: solid; border-width: 1px; border-color: #1a75ff; padding: 7px;" ) # Disable controls self.save_widget.setEnabled(False) self.device_select.setEnabled(False) self.meas_select.setEnabled(False) self.voc_bias.setEnabled(False) self.voc_cmpl.setEnabled(False) self.iv_plot.mpl_refresh_setEnabled(False) self.voc_plot.mpl_refresh_setEnabled(False) self.mpp_plot.mpl_refresh_setEnabled(False) # Run the measurement thread function self.voc_thread = threading.Thread(target=self.exec_voc_thread, args=()) self.voc_thread.daemon = True # Daemonize thread self.voc_thread.start() # Start the execution self.voc_thread_running = True # Set execution flag # Tracking measurement OFF def exec_voc_stop(self): if self.keithley() is not None: # Put measurement button in measure state self.voc_meas_button.setStyleSheet( "background-color: #dddddd; border-style: solid; border-width: 1px; border-color: #aaaaaa; padding: 7px;" ) # Enable controls self.save_widget.setEnabled(True) self.meas_select.setEnabled(True) self.device_select.setEnabled(True) self.voc_bias.setEnabled(True) self.voc_cmpl.setEnabled(True) self.iv_plot.mpl_refresh_setEnabled(True) self.voc_plot.mpl_refresh_setEnabled(True) self.mpp_plot.mpl_refresh_setEnabled(True) # Set thread running to False. This will break the sweep measurements # execution loop on next iteration. self.voc_thread_running = False self.voc_thread.join() # Waits for thread to complete ##################################### # MPP-MONITOR MEASUREMENT MODE # def exec_mpp_thread(self): # Get QVisaDataObject data = self._get_data_object() key = data.add_hash_key("pv-mpp") # Add data fields to key data.set_subkeys(key, ["t", "Vmpp", "Impp", "Pmpp"]) data.set_metadata(key, "__type__", "pv-mpp") # Add key to meta widget self.meta_widget.add_meta_key(key) # Generate colors _c0 = self.mpp_plot.gen_next_color() _c1 = self.mpp_plot.gen_next_color() # Clear plot and zero arrays self.mpp_plot.add_axes_handle('111', key, _color=_c0) self.mpp_plot.add_axes_handle('111t', key, _color=_c1) # Thread start time start = float(time.time()) # Set bias to initial value in voltas and turn output ON self.keithley().set_voltage(self.mpp_bias.value()) self.keithley().current_cmp(self.mpp_cmpl.value()) self.keithley().output_on() # Thread loop while self.mpp_thread_running is True: # Iteration timer _iter_start = float(time.time()) # Covvergence loop _d = [] while True: # Get data from buffer _buffer = self.keithley().meas().split(",") # If convergence takes too long paint a value (10s) if float(time.time() - _iter_start) >= 3.0: break # Otherwise, adjust the voltage proportionally else: # Create 1mV sense amplitude _amplitude = self.mpp_ampl.value() _v, _i = np.add( float(_buffer[0]), np.linspace(-1.0 * _amplitude, _amplitude, 5)), [] # Measure current over sense amplitude array for _ in _v: self.keithley().set_voltage(_) _b = self.keithley().meas().split(",") _i.append(-1.0 * float(_b[1])) # Reset the voltage self.keithley().set_voltage(float(_buffer[0])) # Calculate derivative _p = np.multiply(_i, _v) _d = np.gradient(np.multiply(_i, _v)) _d = np.divide(_d, _amplitude) # Differntial gain controller if np.mean(_d) <= 0.0: self.update_bias( float(_buffer[0]) * float(1.0 - self.mpp_gain.value() / 1000.)) else: self.update_bias( float(_buffer[0]) * float(1.0 + self.mpp_gain.value() / 1000.)) # Extract data from buffer _now = float(time.time() - start) data.append_subkey_data(key, "t", _now) data.append_subkey_data(key, "Vmpp", 1.0 * float(_buffer[0])) data.append_subkey_data(key, "Impp", -1.0 * float(_buffer[1])) data.append_subkey_data( key, "Pmpp", -1.0 * float(_buffer[1]) * float(_buffer[0])) # Append handle data and update canvas self.mpp_plot.append_handle_data("111", key, _now, float(_buffer[0])) self.mpp_plot.append_handle_data( "111t", key, _now, float(_buffer[0]) * -1.0 * float(_buffer[1]) * 1000.) self.mpp_plot.update_canvas() # Measurement delay if self.mpp_delay.value() != 0: time.sleep(self.mpp_delay.value()) # Cleanup after thread termination self.keithley().set_voltage(0.0) self.keithley().output_off() # Tracking measurement ON def exec_mpp_run(self): if self.keithley() is not None: # Update UI for ON state self.mpp_meas_button.setStyleSheet( "background-color: #cce6ff; border-style: solid; border-width: 1px; border-color: #1a75ff; padding: 7px;" ) # Disable widgets self.save_widget.setEnabled(False) self.meas_select.setEnabled(False) self.device_select.setEnabled(False) self.mpp_bias.setEnabled(False) self.mpp_cmpl.setEnabled(False) self.iv_plot.mpl_refresh_setEnabled(False) self.voc_plot.mpl_refresh_setEnabled(False) self.mpp_plot.mpl_refresh_setEnabled(False) # Run the measurement thread function self.mpp_thread = threading.Thread(target=self.exec_mpp_thread, args=()) self.mpp_thread.daemon = True # Daemonize thread self.mpp_thread.start() # Start the execution self.mpp_thread_running = True # Set execution flag # Tracking measurement OFF def exec_mpp_stop(self): if self.keithley() is not None: # Put measurement button in measure state self.mpp_meas_button.setStyleSheet( "background-color: #dddddd; border-style: solid; border-width: 1px; border-color: #aaaaaa; padding: 7px;" ) # Enable widgets self.save_widget.setEnabled(True) self.meas_select.setEnabled(True) self.device_select.setEnabled(True) self.mpp_bias.setEnabled(True) self.mpp_cmpl.setEnabled(True) self.iv_plot.mpl_refresh_setEnabled(True) self.voc_plot.mpl_refresh_setEnabled(True) self.mpp_plot.mpl_refresh_setEnabled(True) # Set thread running to False. This will break the sweep measurements # execution loop on next iteration. self.mpp_thread_running = False self.mpp_thread.join() # Waits for thread to complete
class SetupMachine(QStateMachine): """ Setup game state machine """ action_complete = pyqtSignal() # emitted when action completed time_out = pyqtSignal() # emitted on clock timeout try_again = pyqtSignal() # emitted if repeat action required not_valid = pyqtSignal() # emitted if turn invalid end_game = pyqtSignal() # emitted to end game players_complete = pyqtSignal() # emitted when players set up radio_complete = pyqtSignal(int, int) # emitted when radio button clicked def __init__(self, scene): super(SetupMachine, self).__init__() self.st_code = qstates.States(scene, self) buttons = scene.buttons.buttons self.rootState = None self.languageState, self.loadState, self.instructState = None, None, None self.nameState, self.setplayersState, self.tileState = None, None, None self.checkState, self.setupState, self.startState = None, None, None self.playState, self.blankState, self.acceptState = None, None, None self.passState, self.challengeState, self.exchangeState = None, None, None self.endState, self.quitState = None, None self.set_states() self.set_signal_transitions() self.set_button_transitions(buttons) states = self.assign_name() self.assign_visibility(states, buttons) self.assign_enabled(states, buttons) self.set_structure() self.set_connections() self.start() # start state machine def set_states(self): """ Create state machine states """ self.rootState = QState() # Initial setup states self.languageState = QState(self.rootState) self.loadState = QState(self.rootState) self.instructState = QState(self.rootState) self.nameState = QState(self.rootState) self.setplayersState = QState(self.rootState) self.tileState = QState(self.rootState) self.checkState = QState(self.rootState) self.setupState = QState(self.rootState) # Wait state between turns self.startState = QState(self.rootState) # Playing states self.playState = QState(self.rootState) self.blankState = QState(self.rootState) self.acceptState = QState(self.rootState) self.passState = QState(self.rootState) self.challengeState = QState(self.rootState) self.exchangeState = QState(self.rootState) self.endState = QState(self.rootState) # End state self.quitState = QFinalState() def set_signal_transitions(self): """ pyqtSignal transitions from states """ self.loadState.addTransition(self.action_complete, self.instructState) self.setplayersState.addTransition(self.players_complete, self.tileState) self.checkState.addTransition(self.action_complete, self.setupState) self.checkState.addTransition(self.try_again, self.tileState) self.setupState.addTransition(self.action_complete, self.startState) self.blankState.addTransition(self.not_valid, self.playState) self.blankState.addTransition(self.try_again, self.blankState) self.blankState.addTransition(self.action_complete, self.acceptState) self.acceptState.addTransition(self.action_complete, self.startState) self.passState.addTransition(self.action_complete, self.startState) self.challengeState.addTransition(self.action_complete, self.startState) self.rootState.addTransition(self.end_game, self.endState) def set_button_transitions(self, buttons): """ Button transitions from states """ self.languageState.addTransition(buttons["nextButton"].pressed, self.loadState) self.instructState.addTransition(buttons["nextButton"].pressed, self.nameState) self.nameState.addTransition(buttons["nextButton"].pressed, self.setplayersState) self.tileState.addTransition(buttons["nextButton"].pressed, self.checkState) self.acceptState.addTransition(buttons["challengeButton"].pressed, self.challengeState) self.rootState.addTransition(buttons["playButton"].pressed, self.playState) self.rootState.addTransition(buttons["passButton"].pressed, self.passState) self.rootState.addTransition(buttons["exchangeButton"].pressed, self.exchangeState) self.playState.addTransition(buttons["acceptButton"].pressed, self.blankState) self.exchangeState.addTransition(buttons["acceptButton"].pressed, self.acceptState) self.rootState.addTransition(buttons["quitButton"].pressed, self.endState) self.endState.addTransition(buttons["backButton"].pressed, self.startState) self.endState.addTransition(buttons["endButton"].pressed, self.quitState) self.endState.addTransition(buttons["newButton"].pressed, self.nameState) def assign_name(self): """ Assign name to property 'state' for each state """ states = {} self.rootState.assignProperty(self, "state", "root") states["root"] = self.rootState self.languageState.assignProperty(self, "state", "language") states["language"] = self.languageState self.loadState.assignProperty(self, "state", "load") states["load"] = self.loadState self.instructState.assignProperty(self, "state", "instruct") states["instruct"] = self.instructState self.nameState.assignProperty(self, "state", "name") states["name"] = self.nameState self.setplayersState.assignProperty(self, "state", "setplayers") states["setplayers"] = self.setplayersState self.tileState.assignProperty(self, "state", "tiles") states["tiles"] = self.tileState self.checkState.assignProperty(self, "state", "check") states["check"] = self.checkState self.setupState.assignProperty(self, "state", "setup") states["setup"] = self.setupState self.startState.assignProperty(self, "state", "start") states["start"] = self.startState self.playState.assignProperty(self, "state", "play") states["play"] = self.playState self.blankState.assignProperty(self, "state", "blank") states["blank"] = self.blankState self.acceptState.assignProperty(self, "state", "accept") states["accept"] = self.acceptState self.passState.assignProperty(self, "state", "pass") states["pass"] = self.passState self.challengeState.assignProperty(self, "state", "challenge") states["challenge"] = self.challengeState self.exchangeState.assignProperty(self, "state", "exchange") states["exchange"] = self.exchangeState self.endState.assignProperty(self, "state", "end") states["end"] = self.endState return states @staticmethod def assign_visibility(states, buttons): """ Assign visibility property for each button in each state """ visibility = { "language": ["nextButton"], "load": [], "instruct": ["nextButton"], "name": ["nextButton"], "tiles": ["nextButton"], "start": [ "playButton", "acceptButton", "passButton", "challengeButton", "exchangeButton", "quitButton" ], "play": [ "playButton", "acceptButton", "passButton", "challengeButton", "exchangeButton", "quitButton" ], "blank": [ "playButton", "acceptButton", "passButton", "challengeButton", "exchangeButton", "quitButton" ], "accept": [ "playButton", "acceptButton", "passButton", "challengeButton", "exchangeButton", "quitButton" ], "pass": [ "playButton", "acceptButton", "passButton", "challengeButton", "exchangeButton", "quitButton" ], "exchange": [ "playButton", "acceptButton", "passButton", "challengeButton", "exchangeButton", "quitButton" ], "challenge": [ "playButton", "acceptButton", "passButton", "challengeButton", "exchangeButton", "quitButton" ], "end": ["newButton", "endButton", "backButton"] } for name, state in states.items(): button_list = [] if name in visibility: button_list = visibility[name] for k, b in buttons.items(): if k in button_list: state.assignProperty(b, "visible", "True") else: state.assignProperty(b, "visible", "False") @staticmethod def assign_enabled(states, buttons): """ Assign enabled property for each button in each state """ enabled = { "language": ["nextButton"], "load": [], "instruct": ["nextButton"], "name": ["nextButton"], "tiles": ["nextButton"], "start": ["playButton", "quitButton"], "play": ["acceptButton", "passButton", "exchangeButton"], "accept": ["challengeButton"], "pass": ["playButton"], "exchange": ["acceptButton"], "end": ["newButton", "endButton", "backButton"] } for name, state in states.items(): button_list = [] if name in enabled: button_list = enabled[name] for k, b in buttons.items(): if k in button_list: state.assignProperty(b, "enabled", "True") else: state.assignProperty(b, "enabled", "False") def set_structure(self): """ Set initial anf final states """ self.addState(self.rootState) self.addState(self.quitState) self.setInitialState(self.rootState) self.rootState.setInitialState(self.languageState) self.finished.connect(self.end_m) def set_connections(self): """ Set enter and exit connections for states """ self.languageState.entered.connect(self.st_code.s_enter_language) self.languageState.exited.connect(self.st_code.s_exit_language) self.loadState.entered.connect(self.st_code.s_enter_load) self.instructState.entered.connect(self.st_code.s_enter_instruct) self.nameState.entered.connect(self.st_code.s_enter_name) self.setplayersState.entered.connect(self.st_code.s_enter_setplayers) self.setplayersState.exited.connect(self.st_code.s_exit_setplayers) self.tileState.entered.connect(self.st_code.s_enter_tile) self.checkState.entered.connect(self.st_code.s_enter_check) self.setupState.entered.connect(self.st_code.s_enter_setup) self.startState.entered.connect(self.st_code.s_enter_start) self.playState.entered.connect(self.st_code.s_enter_play) self.playState.exited.connect(self.st_code.s_exit_play) self.blankState.entered.connect(self.st_code.s_enter_blank) self.acceptState.entered.connect(self.st_code.s_enter_accept) self.passState.entered.connect(self.st_code.s_enter_pass) self.challengeState.entered.connect(self.st_code.s_enter_challenge) self.exchangeState.entered.connect(self.st_code.s_enter_exchange) self.endState.entered.connect(self.st_code.s_enter_end) self.endState.exited.connect(self.st_code.s_exit_end) @staticmethod def end_m(): """ State machine quit """ sys.exit(0)
class MainWindow(QMainWindow): instrumentsFound = pyqtSignal() sampleFound = pyqtSignal() measurementFinished = pyqtSignal() def __init__(self, parent=None): super().__init__(parent) self.setAttribute(Qt.WA_QuitOnClose) self.setAttribute(Qt.WA_DeleteOnClose) # create instance variables self._ui = uic.loadUi('mainwindow.ui', self) # create models self.measureModels = { 1: MeasureModel(self), 2: MeasureModel(self), } self._instrumentManager = InstrumentManager(self, self.measureModels) self.machine = QStateMachine() self.stateInitial = QState() self.stateReadyToCheck = QState() self.stateReadyToMeasure = QState() self.stateAfterMeasure = QState() self.initDialog() def setupStateMachine(self): self.machine.addState(self.stateInitial) self.machine.addState(self.stateReadyToCheck) self.machine.addState(self.stateReadyToMeasure) self.machine.addState(self.stateAfterMeasure) self.stateInitial.addTransition(self.instrumentsFound, self.stateReadyToCheck) self.stateInitial.assignProperty(self._ui.btnSearchInstruments, 'enabled', 'True') self.stateInitial.assignProperty(self._ui.btnCheckSample, 'enabled', 'False') self.stateInitial.assignProperty(self._ui.btnMeasureStart, 'visible', 'True') self.stateInitial.assignProperty(self._ui.btnMeasureStart, 'enabled', 'False') self.stateInitial.assignProperty(self._ui.btnMeasureStop, 'visible', 'False') self.stateInitial.assignProperty(self._ui.btnMeasureStop, 'enabled', 'False') self.stateInitial.assignProperty(self._ui.radioLetter1, 'checked', 'True') self.stateInitial.assignProperty(self._ui.radioLetter1, 'enabled', 'True') self.stateInitial.assignProperty(self._ui.radioLetter2, 'enabled', 'True') self.stateReadyToCheck.addTransition(self.sampleFound, self.stateReadyToMeasure) self.stateReadyToCheck.assignProperty(self._ui.btnSearchInstruments, 'enabled', 'True') self.stateReadyToCheck.assignProperty(self._ui.btnCheckSample, 'enabled', 'True') self.stateReadyToCheck.assignProperty(self._ui.btnMeasureStart, 'visible', 'True') self.stateReadyToCheck.assignProperty(self._ui.btnMeasureStart, 'enabled', 'False') self.stateReadyToCheck.assignProperty(self._ui.btnMeasureStop, 'visible', 'False') self.stateReadyToCheck.assignProperty(self._ui.btnMeasureStop, 'enabled', 'False') self.stateReadyToCheck.assignProperty(self._ui.radioLetter1, 'enabled', 'True') self.stateReadyToCheck.assignProperty(self._ui.radioLetter2, 'enabled', 'True') self.stateReadyToMeasure.addTransition(self.measurementFinished, self.stateAfterMeasure) self.stateReadyToMeasure.addTransition(self.instrumentsFound, self.stateReadyToCheck) self.stateReadyToMeasure.assignProperty(self._ui.btnSearchInstruments, 'enabled', 'True') self.stateReadyToMeasure.assignProperty(self._ui.btnCheckSample, 'enabled', 'False') self.stateReadyToMeasure.assignProperty(self._ui.btnMeasureStart, 'visible', 'True') self.stateReadyToMeasure.assignProperty(self._ui.btnMeasureStart, 'enabled', 'True') self.stateReadyToMeasure.assignProperty(self._ui.btnMeasureStop, 'visible', 'False') self.stateReadyToMeasure.assignProperty(self._ui.btnMeasureStop, 'enabled', 'False') self.stateReadyToMeasure.assignProperty(self._ui.radioLetter1, 'enabled', 'False') self.stateReadyToMeasure.assignProperty(self._ui.radioLetter2, 'enabled', 'False') self.stateAfterMeasure.addTransition(self._ui.btnMeasureStop.clicked, self.stateReadyToCheck) self.stateAfterMeasure.addTransition(self.instrumentsFound, self.stateReadyToCheck) self.stateAfterMeasure.assignProperty(self._ui.btnSearchInstruments, 'enabled', 'True') self.stateAfterMeasure.assignProperty(self._ui.btnCheckSample, 'enabled', 'False') self.stateAfterMeasure.assignProperty(self._ui.btnMeasureStart, 'visible', 'False') self.stateAfterMeasure.assignProperty(self._ui.btnMeasureStart, 'enabled', 'False') self.stateAfterMeasure.assignProperty(self._ui.btnMeasureStop, 'visible', 'True') self.stateAfterMeasure.assignProperty(self._ui.btnMeasureStop, 'enabled', 'True') self.stateAfterMeasure.assignProperty(self._ui.radioLetter1, 'enabled', 'False') self.stateAfterMeasure.assignProperty(self._ui.radioLetter2, 'enabled', 'False') self.machine.setInitialState(self.stateInitial) self.machine.start() def setupUiSignals(self): self._ui.btnSearchInstruments.clicked.connect( self.onBtnSearchInstrumentsClicked) self._ui.btnCheckSample.clicked.connect(self.onBtnCheckSample) self._ui.btnMeasureStart.clicked.connect(self.onBtnMeasureStart) self._ui.btnMeasureStop.clicked.connect(self.onBtnMeasureStop) self._ui.radioLetter1.toggled.connect(self.onRadioToggled) self._ui.radioLetter2.toggled.connect(self.onRadioToggled) def initDialog(self): self.setupStateMachine() self.setupUiSignals() self._ui.bgrpLetter.setId(self._ui.radioLetter1, 1) self._ui.bgrpLetter.setId(self._ui.radioLetter2, 2) self._ui.textLog.hide() self.refreshView() # UI utility methods def refreshView(self): self.resizeTable() # twidth = self.ui.tableSuggestions.frameGeometry().width() - 30 # self.ui.tableSuggestions.setColumnWidth(0, twidth * 0.05) # self.ui.tableSuggestions.setColumnWidth(1, twidth * 0.10) # self.ui.tableSuggestions.setColumnWidth(2, twidth * 0.55) # self.ui.tableSuggestions.setColumnWidth(3, twidth * 0.10) # self.ui.tableSuggestions.setColumnWidth(4, twidth * 0.15) # self.ui.tableSuggestions.setColumnWidth(5, twidth * 0.05) def resizeTable(self): self._ui.tableMeasure.resizeRowsToContents() self._ui.tableMeasure.resizeColumnsToContents() def search(self): if not self._instrumentManager.findInstruments(): QMessageBox.information( self, "Ошибка", "Не удалось найти инструменты, проверьте подключение.\nПодробности в логах." ) return False print('found all instruments, enabling sample test') return True # event handlers def resizeEvent(self, event): self.refreshView() # TODO: extract to a measurement manager class def onBtnSearchInstrumentsClicked(self): if not self.search(): return self.stateReadyToCheck.assignProperty( self._ui.editSource, 'text', str(self._instrumentManager._source)) self.stateReadyToCheck.assignProperty( self._ui.editGen1, 'text', str(self._instrumentManager._generator1)) self.stateReadyToCheck.assignProperty( self._ui.editGen2, 'text', str(self._instrumentManager._generator2)) self.stateReadyToCheck.assignProperty( self._ui.editAnalyzer, 'text', str(self._instrumentManager._analyzer)) self.instrumentsFound.emit() def failWith(self, message): QMessageBox.information(self, "Ошибка", message) self.instrumentsFound.emit() def onBtnCheckSample(self): if not self._instrumentManager.checkSample(): self.failWith( "Не удалось найти образец, проверьте подключение.\nПодробности в логах." ) print('sample not detected') return if not self._instrumentManager.checkTaskTable(): self.failWith( "Ошибка при чтении таблицы с заданием на измерение.\nПодробности в логах." ) print('error opening table') return self.sampleFound.emit() self.refreshView() def onBtnMeasureStart(self): print('start measurement task') if not self._instrumentManager.checkSample(): self.failWith( "Не удалось найти образец, проверьте подключение.\nПодробности в логах." ) print('sample not detected') return self._instrumentManager.measure(self._ui.bgrpLetter.checkedId()) self.measurementFinished.emit() self.refreshView() def onBtnMeasureStop(self): # TODO implement print('abort measurement task') def onRadioToggled(self, checked): if not checked: return letter = self._ui.bgrpLetter.checkedId() print('switching to letter', letter) self._ui.tableMeasure.setModel(self.measureModels[letter]) self.refreshView()
view.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) view.show() states = QStateMachine() states.addState(rootState) states.setInitialState(rootState) rootState.setInitialState(centeredState) group = QParallelAnimationGroup() for i, item in enumerate(items): anim = QPropertyAnimation(item, b'pos') anim.setDuration(750 + i * 25) anim.setEasingCurve(QEasingCurve.InOutBack) group.addAnimation(anim) trans = rootState.addTransition(ellipseButton.pressed, ellipseState) trans.addAnimation(group) trans = rootState.addTransition(figure8Button.pressed, figure8State) trans.addAnimation(group) trans = rootState.addTransition(randomButton.pressed, randomState) trans.addAnimation(group) trans = rootState.addTransition(tiledButton.pressed, tiledState) trans.addAnimation(group) trans = rootState.addTransition(centeredButton.pressed, centeredState) trans.addAnimation(group) timer = QTimer()
class SetupMachine(QStateMachine): """ Setup game state machine """ action_complete = pyqtSignal() # emitted when action completed def __init__(self, scene): super(SetupMachine, self).__init__() self.st_code = qstates.States(scene, self) self.rootState, self.waitState, self.setupState, self.loadState = None, None, None, None self.saveState, self.solveState, self.stepState, self.clearState = None, None, None, None self.playState, self.checkState, self.hintState, self.restartState = None, None, None, None self.printState, self.quitState = None, None buttons = scene.buttons.buttons self.set_states() self.set_signal_transitions() self.set_button_transitions(buttons) states = self.assign_name() self.assign_visibility(states, buttons) self.assign_enabled(states, buttons) self.set_structure() self.set_connections() self.start() # start state machine def set_states(self): """ Create state machine states """ self.rootState = QState() # Initial setup states self.waitState = QState(self.rootState) self.setupState = QState(self.rootState) self.loadState = QState(self.rootState) self.saveState = QState(self.rootState) self.solveState = QState(self.rootState) self.stepState = QState(self.rootState) self.clearState = QState(self.rootState) self.playState = QState(self.rootState) self.checkState = QState(self.rootState) self.hintState = QState(self.rootState) self.restartState = QState(self.rootState) self.printState = QState(self.rootState) # End state self.quitState = QFinalState() def set_signal_transitions(self): """ pyqtSignal transitions from states """ self.setupState.addTransition(self.action_complete, self.waitState) self.solveState.addTransition(self.action_complete, self.waitState) self.stepState.addTransition(self.action_complete, self.waitState) self.loadState.addTransition(self.action_complete, self.waitState) self.saveState.addTransition(self.action_complete, self.waitState) self.clearState.addTransition(self.action_complete, self.waitState) self.hintState.addTransition(self.action_complete, self.waitState) self.restartState.addTransition(self.action_complete, self.waitState) self.printState.addTransition(self.action_complete, self.waitState) self.checkState.addTransition(self.action_complete, self.waitState) def set_button_transitions(self, buttons): """ Button transitions from states """ self.waitState.addTransition(buttons["setupButton"].pressed, self.setupState) self.setupState.addTransition(buttons["setupButton"].pressed, self.waitState) self.waitState.addTransition(buttons["solveButton"].pressed, self.solveState) self.waitState.addTransition(buttons["stepButton"].pressed, self.stepState) self.waitState.addTransition(buttons["loadButton"].pressed, self.loadState) self.waitState.addTransition(buttons["saveButton"].pressed, self.saveState) self.waitState.addTransition(buttons["clearButton"].pressed, self.clearState) self.waitState.addTransition(buttons["playButton"].pressed, self.playState) self.playState.addTransition(buttons["playButton"].pressed, self.waitState) self.waitState.addTransition(buttons["hintButton"].pressed, self.hintState) self.hintState.addTransition(buttons["hintButton"].pressed, self.waitState) self.waitState.addTransition(buttons["restartButton"].pressed, self.restartState) self.waitState.addTransition(buttons["printButton"].pressed, self.printState) self.waitState.addTransition(buttons["checkButton"].pressed, self.checkState) self.checkState.addTransition(buttons["checkButton"].pressed, self.checkState) self.rootState.addTransition(buttons["quitButton"].pressed, self.quitState) def assign_name(self): """ Assign name to property 'state' for each state """ states = {} self.rootState.assignProperty(self, "state", "root") states["root"] = self.rootState self.waitState.assignProperty(self, "state", "wait") states["wait"] = self.waitState self.setupState.assignProperty(self, "state", "setup") states["setup"] = self.setupState self.loadState.assignProperty(self, "state", "load") states["load"] = self.loadState self.saveState.assignProperty(self, "state", "save") states["save"] = self.saveState self.clearState.assignProperty(self, "state", "clear") states["clear"] = self.clearState self.solveState.assignProperty(self, "state", "solve") states["solve"] = self.solveState self.stepState.assignProperty(self, "state", "step") states["step"] = self.stepState self.playState.assignProperty(self, "state", "play") states["play"] = self.playState self.hintState.assignProperty(self, "state", "hint") states["hint"] = self.hintState self.restartState.assignProperty(self, "state", "restart") states["restart"] = self.restartState self.printState.assignProperty(self, "state", "print") states["print"] = self.printState self.checkState.assignProperty(self, "state", "check") states["check"] = self.checkState return states @staticmethod def assign_visibility(states, buttons): """ Assign visibility property for each button in each state """ visibility = { "wait": [ "setupButton", "checkButton", "loadButton", "saveButton", "clearButton", "playButton", "printButton", "solveButton", "stepButton", "quitButton", "hintButton", "restartButton" ], "load": [ "setupButton", "checkButton", "loadButton", "saveButton", "printButton", "clearButton", "playButton", "solveButton", "stepButton", "quitButton", "hintButton", "restartButton" ], "save": [ "setupButton", "checkButton", "loadButton", "saveButton", "printButton", "clearButton", "playButton", "solveButton", "stepButton", "quitButton", "hintButton", "restartButton" ], "setup": [ "setupButton", "checkButton", "loadButton", "saveButton", "printButton", "clearButton", "playButton", "solveButton", "stepButton", "quitButton", "hintButton", "restartButton" ], "solve": [ "setupButton", "checkButton", "loadButton", "saveButton", "printButton", "clearButton", "playButton", "solveButton", "stepButton", "quitButton", "hintButton", "restartButton" ], "step": [ "setupButton", "checkButton", "loadButton", "saveButton", "printButton", "clearButton", "playButton", "solveButton", "stepButton", "quitButton", "hintButton", "restartButton" ], "play": [ "setupButton", "checkButton", "loadButton", "saveButton", "printButton", "clearButton", "playButton", "solveButton", "stepButton", "quitButton", "hintButton", "restartButton" ], "hint": [ "setupButton", "checkButton", "loadButton", "saveButton", "printButton", "clearButton", "playButton", "solveButton", "stepButton", "quitButton", "hintButton", "restartButton" ], "print": [ "setupButton", "checkButton", "loadButton", "saveButton", "printButton", "clearButton", "playButton", "solveButton", "stepButton", "quitButton", "hintButton", "restartButton" ], "check": [ "setupButton", "checkButton", "loadButton", "saveButton", "printButton", "clearButton", "playButton", "solveButton", "stepButton", "quitButton", "hintButton", "restartButton" ] } for name, state in states.items(): button_list = [] if name in visibility: button_list = visibility[name] for k, b in buttons.items(): if k in button_list: state.assignProperty(b, "visible", "True") else: state.assignProperty(b, "visible", "False") @staticmethod def assign_enabled(states, buttons): """ Assign enabled property for each button in each state """ enabled = { "wait": [ "setupButton", "checkButton", "loadButton", "saveButton", "clearButton", "playButton", "printButton", "solveButton", "stepButton", "quitButton", "hintButton", "restartButton" ], "load": [ "setupButton", "checkButton", "loadButton", "saveButton", "printButton", "clearButton", "playButton", "solveButton", "stepButton", "quitButton", "hintButton", "restartButton" ], "save": [ "setupButton", "checkButton", "loadButton", "saveButton", "printButton", "clearButton", "playButton", "solveButton", "stepButton", "quitButton", "hintButton", "restartButton" ], "setup": [ "setupButton", "loadButton", "saveButton", "printButton", "clearButton", "quitButton", "hintButton", "restartButton" ], "solve": [ "setupButton", "checkButton", "loadButton", "saveButton", "printButton", "clearButton", "playButton", "solveButton", "stepButton", "quitButton", "hintButton", "restartButton" ], "step": [ "setupButton", "checkButton", "loadButton", "saveButton", "printButton", "clearButton", "playButton", "solveButton", "stepButton", "quitButton", "hintButton", "restartButton" ], "play": [ "checkButton", "saveButton", "playButton", "printButton", "clearButton", "solveButton", "stepButton", "quitButton", "hintButton", "restartButton" ], "hint": [ "setupButton", "checkButton", "loadButton", "saveButton", "printButton", "clearButton", "playButton", "solveButton", "stepButton", "quitButton", "hintButton", "restartButton" ], "print": [ "setupButton", "checkButton", "loadButton", "saveButton", "printButton", "clearButton", "playButton", "solveButton", "stepButton", "quitButton", "hintButton", "restartButton" ], "check": [ "setupButton", "checkButton", "loadButton", "saveButton", "printButton", "clearButton", "playButton", "solveButton", "stepButton", "quitButton", "hintButton", "restartButton" ] } for name, state in states.items(): button_list = [] if name in enabled: button_list = enabled[name] for k, b in buttons.items(): if k in button_list: state.assignProperty(b, "enabled", "True") else: state.assignProperty(b, "enabled", "False") def set_structure(self): """ Set initial anf final states """ self.addState(self.rootState) self.addState(self.quitState) self.setInitialState(self.rootState) self.rootState.setInitialState(self.waitState) self.finished.connect(self.end_m) def set_connections(self): """ Set enter and exit connections for states """ self.waitState.entered.connect(self.st_code.s_enter_wait) self.waitState.exited.connect(self.st_code.s_exit_wait) self.setupState.entered.connect(self.st_code.s_enter_setup) self.setupState.exited.connect(self.st_code.s_exit_setup) self.loadState.entered.connect(self.st_code.s_enter_load) self.loadState.exited.connect(self.st_code.s_exit_load) self.saveState.entered.connect(self.st_code.s_enter_save) self.saveState.exited.connect(self.st_code.s_exit_save) self.solveState.entered.connect(self.st_code.s_enter_solve) self.solveState.exited.connect(self.st_code.s_exit_solve) self.stepState.entered.connect(self.st_code.s_enter_step) self.stepState.exited.connect(self.st_code.s_exit_step) self.clearState.entered.connect(self.st_code.s_enter_clear) self.clearState.exited.connect(self.st_code.s_exit_clear) self.playState.entered.connect(self.st_code.s_enter_play) self.playState.exited.connect(self.st_code.s_exit_play) self.hintState.entered.connect(self.st_code.s_enter_hint) self.hintState.exited.connect(self.st_code.s_exit_hint) self.restartState.entered.connect(self.st_code.s_enter_restart) self.restartState.exited.connect(self.st_code.s_exit_restart) self.printState.entered.connect(self.st_code.s_enter_print) self.printState.exited.connect(self.st_code.s_exit_print) self.checkState.entered.connect(self.st_code.s_enter_check) self.checkState.exited.connect(self.st_code.s_exit_check) @staticmethod def end_m(): """ State machine quit """ sys.exit(0)
def __init__(self, parent): super(DrawLotteryView, self).__init__() self.pwindow = parent #获取父窗口指针 self.states = QStateMachine() sinitinfo = QState() sltypeinfo = QState() sprizeinfo = QState() svnumberwindow = QState() sdrawlottery = QState() sfinal = QState() sinitinfo.addTransition(self.on_nextstep_event, sltypeinfo) sltypeinfo.addTransition(self.on_nextstep_event, sprizeinfo) sprizeinfo.addTransition(self.on_nextstep_event, svnumberwindow) svnumberwindow.addTransition(self.on_nextstep_event, sdrawlottery) sdrawlottery.addTransition(self.on_nextstep_event, sfinal) sfinal.addTransition(self.on_final_event, sinitinfo) sinitinfo.entered.connect(self.initinfo) sltypeinfo.entered.connect(self.viewltypeinfo) sprizeinfo.entered.connect(self.viewprizeinfo) svnumberwindow.entered.connect(self.viewnumberwindow) sdrawlottery.entered.connect(self.drawlottery) sfinal.entered.connect(self.final) self.states.addState(sinitinfo) self.states.addState(sltypeinfo) self.states.addState(sprizeinfo) self.states.addState(svnumberwindow) self.states.addState(sdrawlottery) self.states.addState(sfinal) self.states.setInitialState(sinitinfo) self.states.start()