def ui_setup_coord(self, coord: str, unite: str): """Configure un duo de widget (QLabel et QLCDNumber dans un QLayout) et renvoie le QLCDNumber""" label_coord = QLabel() label_coord.setText('{0} ({1})'.format(coord, unite)) self.layout_coord.addWidget(label_coord) lcd_number_coord = QLCDNumber() lcd_number_coord.setFixedSize(QLCD_SIZE1) self.layout_coord.addWidget(lcd_number_coord) return lcd_number_coord
class PlayTimer(QWidget): done = pyqtSignal() def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.init_ui() def init_ui(self): self.setProperty('id', 'timer') vbox = QVBoxLayout(self) self.instructions = QLabel(self) self.instructions.setProperty("id", "timer-instruction") self.lcd = QLCDNumber(2, self) self.clock = QBasicTimer() vbox.addWidget(self.instructions) vbox.addWidget(self.lcd) vbox.setAlignment(Qt.AlignCenter) vbox.setAlignment(self.instructions, Qt.AlignCenter) def timerEvent(self, e): if self.preptime > 1: self.preptime -= 1 self.lcd.display(self.preptime) elif self.runtime == 60: self.lcd.display(self.runtime) self.runtime -= 1 self.instructions.setText("Play!") elif self.runtime > 0: self.lcd.display(self.runtime) self.runtime -= 1 else: self.clock.stop() self.done.emit() def resizeEvent(self, e): self.lcd.setFixedSize(e.size().width() // 2, e.size().height() // 2) def start_timer(self): self.preptime, self.runtime = 3, 60 self.instructions.setText("Get ready!") self.lcd.display(self.preptime) self.clock.start(1000, self)
class MainWidget(QWidget): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) layout = QHBoxLayout(self) # Main layout of the widget # Creating a group box with a title for each of the widget's parts. Adding a layout for each of the group boxes. box_labels = ['Display', 'Sweep control', 'Switch'] self.group_box = {} self.group_box_layout = {} for label in box_labels: self.group_box_layout[label] = QGridLayout( ) # Creating a layout for each group box self.group_box[label] = QGroupBox(label) # Creating a group box self.group_box[label].setLayout( self.group_box_layout[label] ) # Setting layouts to the group boxes layout.addWidget(self.group_box[label] ) # Setting group boxes to the main layout # Creating an lcd number to be a value monitor and adding it to the layout of the 'Display' group box self.value_lcd = QLCDNumber(6) self.value_lcd.setSmallDecimalPoint(True) self.value_lcd.display('0.0000') self.value_lcd.setFixedSize(320, 85) self.group_box_layout['Display'].addWidget(self.value_lcd, 0, 0, 4, 1, alignment=Qt.AlignCenter) # Creating indicators for all the gui indicator_labels = [ 'Clamped', 'Persistent', 'Sweep limit', 'Quench', 'Hold', 'To zero', 'To set', 'Heater' ] indicator_orders = [ 'i-l', 'i-l', 'i-l', 'i-l', 'l-i', 'l-i', 'l-i', 'l-i' ] indicator_alignments = ['h', 'h', 'h', 'h', 'v', 'v', 'v', 'v'] self.indicator = {} self.sweep_control_btn = {} self.heater_btn = Button() k = 0 for label, order, alignment in zip(indicator_labels, indicator_orders, indicator_alignments): self.indicator[label] = Indicator(label, alignment, order, 12) if k < 4: # Adding corresponding indicators to the 'Display' layout self.group_box_layout['Display'].addWidget( self.indicator[label], k, 1, alignment=Qt.AlignLeft) elif k < 7: # Adding corresponding indicators to the 'Sweep control' layout. Also creating buttons and adding # them as well self.group_box_layout['Sweep control'].addWidget( self.indicator[label], 0, k, alignment=Qt.AlignCenter) self.sweep_control_btn[label] = Button() self.group_box_layout['Sweep control'].addWidget( self.sweep_control_btn[label], 1, k, alignment=Qt.AlignCenter) else: # Adding a 'Heater' indicator to the 'Switch' group box layout. Adding a button to switch the heater self.group_box_layout['Switch'].addWidget( self.indicator[label], 0, 0, alignment=Qt.AlignCenter) self.group_box_layout['Switch'].addWidget( self.heater_btn, 1, 0, alignment=Qt.AlignCenter) k += 1
class DisplayRobot(anr.Robot, QWidget): """Une combinaison de l'objet Robot et d'un QWidget""" def __init__(self, parent_annu, rid): self.parent_annu = parent_annu self.backend = self.parent_annu.backend anr.Robot.__init__(self, rid) QWidget.__init__(self) self.is_ghost = self.rid[-6:] == '_ghost' self.ping = 0 # Création des widgets de la boite robot self.groupbox_robots = QWidget() self.layout_tab_robot = QVBoxLayout(self) self.layout_box_robot = QVBoxLayout(self.groupbox_robots) self.scroll_area = QScrollArea() self.layout_name_delete = QHBoxLayout() self.button_delete = QPushButton() self.layout_coord = QHBoxLayout() self.layout_last_message = QHBoxLayout() self.groupbox_actuators = QGroupBox() self.groupbox_sensors = QGroupBox() self.layout_box_actuators = QVBoxLayout(self.groupbox_actuators) self.layout_box_sensors = QVBoxLayout(self.groupbox_sensors) self.label_last_message = QLabel() self.lcdnumber_las_message = QLCDNumber() self.layout_last_command = QHBoxLayout() self.label_position_command = QLabel() self.qlineedit_pos_cmd = QLineEdit() self.emergency_button = QPushButton() self.progressbar_battery = QProgressBar() # Configuration des widgets de la boite robot self.ui_setup_tab_robot() # Création d'un QTimer pour la mise à jour du ping du robot self.timer = QTimer() self.timer.timeout.connect(self.update_ping) self.timer.start(100) def ui_setup_tab_robot(self): """ Configure l'ensemble de l'onglet robot""" # Configuration de la scroll bar self.scroll_area.setWidgetResizable(True) self.scroll_area.setFrameShape(QFrame.NoFrame) self.scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.scroll_area.setWidget(self.groupbox_robots) self.layout_tab_robot.addWidget(self.scroll_area) self.button_delete.setFixedSize(175, 25) if self.is_ghost: self.button_delete.setText("Oublier") self.button_delete.clicked.connect(lambda: self.backend.forget_robot(self.rid)) else: self.button_delete.setText("Eteindre") self.button_delete.clicked.connect(lambda: self.backend.stopandforget_robot(self.rid)) self.emergency_button.setText("STOP") self.emergency_button.setStyleSheet(EMERGENCY_BUTTON) if self.is_ghost: self.emergency_button.setText("Lecture") self.emergency_button.setStyleSheet(READONLY_BUTTON) self.emergency_button.setFixedSize(175, 25) if not self.is_ghost: self.emergency_button.clicked.connect( lambda: self.backend.emergency_stop_robot(self.rid)) self.layout_name_delete.addWidget(self.button_delete) self.layout_name_delete.addWidget(self.emergency_button) self.layout_box_robot.addLayout(self.layout_name_delete) # Configuration de l'affichage des coordonnées" self.lcdnumber_x = self.ui_setup_coord("X", "mm") self.lcdnumber_y = self.ui_setup_coord("Y", "mm") self.lcdnumber_theta = self.ui_setup_coord("θ", "°") self.layout_box_robot.addLayout(self.layout_coord) # Configuration de l'affichage du dernier message reçu self.label_last_message.setText("Dernière MAJ (s)") self.layout_last_message.addWidget(self.label_last_message) self.lcdnumber_las_message.setFixedSize(QLCD_SIZE2) self.layout_last_message.addWidget(self.lcdnumber_las_message) self.layout_box_robot.addLayout(self.layout_last_message) # Confiuration de l'envoyeur de commandes de postion self.label_position_command.setText("Dern. PosCmd:") self.layout_last_command.addWidget(self.label_position_command) self.qlineedit_pos_cmd = QLineEdit() self.qlineedit_pos_cmd.setText("1500 : 1000: 000") self.qlineedit_pos_cmd.setInputMask("0000 : 0000 : 000") self.qlineedit_pos_cmd.setFixedSize(220, 25) self.qlineedit_pos_cmd.editingFinished.connect(self.on_editing_finished) self.qlineedit_pos_cmd.setAlignment(QT_CENTER) self.layout_last_command.addWidget(self.qlineedit_pos_cmd) self.layout_box_robot.addLayout(self.layout_last_command) # Configuration de la Configure la boite actionneurs self.groupbox_actuators.setAlignment(QT_CENTER) self.groupbox_actuators.setTitle("Actionneurs") self.layout_box_robot.addWidget(self.groupbox_actuators, 0, QT_TOP) # Configuration de la boite capteurs self.groupbox_sensors.setAlignment(QT_CENTER) self.groupbox_sensors.setTitle("Capteurs:") self.layout_box_robot.addWidget(self.groupbox_sensors, 0, QT_TOP) def ui_setup_coord(self, coord: str, unite: str): """Configure un duo de widget (QLabel et QLCDNumber dans un QLayout) et renvoie le QLCDNumber""" label_coord = QLabel() label_coord.setText('{0} ({1})'.format(coord, unite)) self.layout_coord.addWidget(label_coord) lcd_number_coord = QLCDNumber() lcd_number_coord.setFixedSize(QLCD_SIZE1) self.layout_coord.addWidget(lcd_number_coord) return lcd_number_coord def set_pos(self, x, y, theta): """Met à jour la position du robot Entrée: - x (float) - y (float) - theta (float) """ anr.Robot.set_pos(self, x, y, theta) # Mise à jour des valeurs affichées par les QLCDNUmber self.lcdnumber_x.display(self.x) self.lcdnumber_y.display(self.y) self.lcdnumber_theta.display(self.theta) self.update_ping() def create_eqp(self, eqp_name, eqp_type, *args): """Crée un nouvel équipement, et l'ajoute au robot (sans avoir besoin de manipuler des objets Equipement Entrée: - eqp_name (str) - eqp_type (str): le type d'équipement, à choisir en inscrivant la chaine de caractère du nom de classe associé: 'Equipement' / 'Actionneur' / 'Binaire' / 'Capteur' - args (tuple): tous les autres arguments liés à la création des eqps si actionneur ou capteur: (min, max, step (, unit)) """ nv_eqp = None if eqp_type == "Actionneur": min_v = args[0] max_v = args[1] step = args[2] if len(args) == 4: unit = args[3] else: unit = None nv_eqp = DisplayActionneur(self, eqp_name, min_v, max_v, step, unit) elif eqp_type == "Binaire": nv_eqp = DisplayBinaire(self, eqp_name) elif eqp_type == "Capteur": min_v = args[0] max_v = args[1] step = args[2] if len(args) == 4: unit = args[3] else: unit = None nv_eqp = DisplayCapteur(self, eqp_name, min_v, max_v, step, unit) if nv_eqp is not None: self.updt_eqp(nv_eqp) def updt_eqp(self, equipement): """Ajoute/met à jour un actionneur du robot Entrée: - equipement (Equipement) """ #l'équipement existe-t-til déjà? if self.equipements.get(equipement.nom, None) is not None: self.equipements[equipement.nom].hide() #suppression de la partie graphique anr.Robot.updt_eqp(self, equipement) #mise à jour de l'équipement (data) #ajout de la partie graphique au bon layout if isinstance(equipement, DisplayCapteur): self.layout_box_sensors.addWidget(self.equipements[equipement.nom]) else: self.layout_box_actuators.addWidget(self.equipements[equipement.nom]) self.equipements[equipement.nom].show() #affichage partie graphique #cache des groupbox vides has_act = False has_capt = False for eqp_rb in self.equipements.values(): if isinstance(eqp_rb, DisplayCapteur): has_capt = True if isinstance(eqp_rb, DisplayBinaire) or isinstance(eqp_rb, DisplayActionneur): has_act = True if not has_capt: self.groupbox_sensors.hide() else: self.groupbox_sensors.show() if not has_act: self.groupbox_actuators.hide() else: self.groupbox_actuators.show() def remove_eqp(self, eqp_name): """Enlève un équipement repéré par son nom du robot Entrée: - eqp_name (str)""" self.equipements[eqp_name].hide() self.equipements[eqp_name].setParent(None) anr.Robot.remove_eqp(self, eqp_name) def update_ping(self): """ Calcul et met à jour le ping de la position """ self.ping = round(abs(time.time() - self.last_updt_pos), 1) self.lcdnumber_las_message.display(format(self.ping)) for eqp_rb in self.equipements.values(): eqp_rb.update_ping() @pyqtSlot() def on_editing_finished(self): """"Appelée après la fin de l'édition de self.qlineedit_pos_cmd""" cmd = [int(i) for i in self.qlineedit_pos_cmd.text().split(' : ')] self.backend.sendposcmd_robot(self.rid, cmd)
class DisplayActionneur(anr.Actionneur, QWidget): """ Combinaison d'un objet Actionneur et d'un QWidget """ def __init__(self, parent_robot, nom, min_val, max_val, step=1, unite=None): QWidget.__init__(self) anr.Actionneur.__init__(self, nom, min_val, max_val, step, unite) self.parent_robot = parent_robot self.backend = self.parent_robot.backend self.updated_outside = False self.ping = 0 # Création des widgets de l'équipement self.gridlayout_eqp = QGridLayout(self) self.spaceritem_equipement = QSpacerItem(1, 15) self.label_name_equipement = QLabel() self.label_message_equipement = QLabel("Dernière MAJ (s)") self.lcdnumber_ping_eqp = QLCDNumber() self.layout_discret = QHBoxLayout() self.slider_equipement = QSlider(Qt.Horizontal) self.doublespinbox_eqp = QDoubleSpinBox() self.label_command = QLineEdit() self.label_last_command = QLabel() # Configuration des widgets de l'équipement self.ui_setup_equipement() #calcul et mise à jour du ping def update_ping(self): """Mise à jour du ping de l'équipement""" self.ping = round(abs(time.time() - self.last_updt), 1) self.lcdnumber_ping_eqp.display(format(self.ping)) def ui_setup_equipement(self): """ Configure l'ensemble des widgets de l'équipement""" self.gridlayout_eqp.setAlignment(QT_TOP) if self.unite == "None" or self.unite is None: self.label_name_equipement.setText(self.nom) else: self.label_name_equipement.setText('{0} ({1})'.format(self.nom, self.unite)) self.gridlayout_eqp.addWidget(self.label_name_equipement, 0, 0, 1, 1, QT_LEFT) self.label_message_equipement.setText("Dernière MAJ (s)") self.gridlayout_eqp.addWidget(self.label_message_equipement, 2, 0, 1, 2, QT_LEFT) self.lcdnumber_ping_eqp.setMaximumSize(QSize(75, 25)) self.lcdnumber_ping_eqp.setFixedSize(QLCD_SIZE2) self.gridlayout_eqp.addWidget(self.lcdnumber_ping_eqp, 2, 1, 1, 1, QT_RIGHT) self.slider_equipement.setFixedSize(100, 30) self.slider_equipement.setMinimum(self.min_val) self.slider_equipement.setMaximum(self.max_val) self.slider_equipement.setSingleStep(self.step) self.slider_equipement.valueChanged.connect(self.onvaluechanged_slider) self.layout_discret.addWidget(self.slider_equipement) self.doublespinbox_eqp.setFixedSize(75, 30) self.doublespinbox_eqp.setMaximum(self.max_val) self.doublespinbox_eqp.setMinimum(self.min_val) self.doublespinbox_eqp.setSingleStep(self.step) self.doublespinbox_eqp.setAlignment(QT_CENTER) self.doublespinbox_eqp.valueChanged.connect(self.onvaluechanged) self.layout_discret.addWidget(self.doublespinbox_eqp) self.gridlayout_eqp.addLayout(self.layout_discret, 0, 1, 1, 1, QT_RIGHT) self.label_command.setText("None") self.label_command.setFixedSize(75, 30) self.label_command.setReadOnly(True) self.label_command.setAlignment(QT_CENTER) self.gridlayout_eqp.addWidget(self.label_command, 1, 1, 1, 1, QT_RIGHT) self.label_last_command.setText("Dern. Cmd:") self.gridlayout_eqp.addWidget(self.label_last_command, 1, 0, 1, 1, QT_LEFT) def set_state(self, valeur): """Change la valeur Entrée: - valeur (float)""" anr.Binaire.set_state(self, valeur) self.updated_outside = True self.slider_equipement.setValue(int(valeur)) self.doublespinbox_eqp.setValue(valeur) self.updated_outside = False def updt_cmd(self, state): """Met à jour le timestamp de dernière commande et la dernière commande""" anr.Binaire.updt_cmd(self, state) self.label_command.setText(str(state)) @pyqtSlot() def onvaluechanged(self): """ Affiche et envoie vers backend la dernière commande d'un actionneur discret""" if not self.updated_outside: self.backend.sendeqpcmd(self.parent_robot.rid, self.nom, self.doublespinbox_eqp.value()) self.label_command.setText(str(self.doublespinbox_eqp.value())) self.slider_equipement.setValue(int(self.doublespinbox_eqp.value())) self.updt_cmd(self.doublespinbox_eqp.value()) @pyqtSlot() def onvaluechanged_slider(self): """ Affiche et envoie vers backend la dernière commande d'un actionneur discret""" if not self.updated_outside: self.backend.sendeqpcmd(self.parent_robot.rid, self.nom, self.doublespinbox_eqp.value()) self.label_command.setText(str(self.slider_equipement.value())) self.doublespinbox_eqp.setValue(self.slider_equipement.value()) self.updt_cmd(self.slider_equipement.value())
class DisplayCapteur(anr.Capteur, QWidget): """Une combinaison de Capteur et d'un QWidget""" def __init__(self, parent_robot, nom, min_val, max_val, step=1, unite=None): QWidget.__init__(self) anr.Capteur.__init__(self, nom, min_val, max_val, step, unite) self.parent_robot = parent_robot self.backend = self.parent_robot.backend self.updated_outside = False self.ping = 0 # Création des widgets de l'équipement self.gridlayout_eqp = QGridLayout(self) self.spaceritem_equipement = QSpacerItem(1, 15) self.label_name_equipement = QLabel() self.label_message_equipement = QLabel("Dernière MAJ (s)") self.lcdnumber_ping_eqp = QLCDNumber() self.lcdnumber_eqp = QLCDNumber() self.progressbar_eqp = QProgressBar() # Configuration des widgets de l'équipement self.ui_setup_equipement() def ui_setup_equipement(self): """ Configure l'ensemble des widgets de l'équipement""" self.gridlayout_eqp.setAlignment(QT_TOP) if self.unite == "None" or self.unite is None: self.label_name_equipement.setText(self.nom) else: self.label_name_equipement.setText('{0} ({1})'.format(self.nom, self.unite)) self.gridlayout_eqp.addWidget(self.label_name_equipement, 0, 0, 1, 1, QT_LEFT) self.label_message_equipement.setText("Dernière MAJ (s)") self.gridlayout_eqp.addWidget(self.label_message_equipement, 2, 0, 1, 2, QT_LEFT) self.lcdnumber_ping_eqp.setMaximumSize(QSize(75, 25)) self.lcdnumber_ping_eqp.setFixedSize(QLCD_SIZE2) self.gridlayout_eqp.addWidget(self.lcdnumber_ping_eqp, 2, 1, 1, 1, QT_RIGHT) if self.min_val is None or self.max_val is None or self.step is None: self.lcdnumber_eqp.setMinimumSize(150, 30) self.gridlayout_eqp.addWidget(self.lcdnumber_eqp, 0, 1, 1, 1, QT_RIGHT) self.progressbar_eqp.hide() else: self.progressbar_eqp.setRange(int(self.min_val), int(self.max_val)) self.progressbar_eqp.setAlignment(QT_CENTER) self.progressbar_eqp.setFormat("%v") self.progressbar_eqp.setFixedSize(150, 30) self.gridlayout_eqp.addWidget(self.progressbar_eqp, 0, 1, 1, 1, QT_RIGHT) self.lcdnumber_eqp.hide() #calcul et mise à jour du ping def update_ping(self): """Mise à jour du ping de l'équipement""" self.ping = round(abs(time.time() - self.last_updt), 1) self.lcdnumber_ping_eqp.display(format(self.ping)) def set_state(self, valeur): """Change la valeur Entrée: - valeur (float)""" anr.Binaire.set_state(self, valeur) self.updated_outside = True if self.valeur is not None: self.lcdnumber_eqp.display(self.valeur) self.progressbar_eqp.setValue(int(self.valeur)) self.updated_outside = False
class DisplayBinaire(anr.Binaire, QWidget): """Une combinaison de l'objet Equipement et d'un QWidget""" def __init__(self, parent, nom): QWidget.__init__(self) anr.Binaire.__init__(self, nom) self.parent_robot = parent self.backend = self.parent_robot.backend self.updated_outside = False self.ping = 0 # Création des widgets de l'équipement self.gridlayout_eqp = QGridLayout(self) self.spaceritem_equipement = QSpacerItem(1, 15) self.label_name_equipement = QLabel() self.label_message_equipement = QLabel("Dernière MAJ (s)") self.lcdnumber_ping_eqp = QLCDNumber() self.layout_binaire = QHBoxLayout() self.checkbox_equipement = QCheckBox() self.label_command = QLineEdit() self.label_last_command = QLabel() self.label_binaire = QLabel() # Configuration des widgets de l'équipement self.ui_setup_equipement() def ui_setup_equipement(self): """ Configure l'ensemble des widgets de l'équipement""" self.gridlayout_eqp.setAlignment(QT_TOP) if self.unite == "None" or self.unite is None: self.label_name_equipement.setText(self.nom) else: self.label_name_equipement.setText('{0} ({1})'.format(self.nom, self.unite)) self.gridlayout_eqp.addWidget(self.label_name_equipement, 0, 0, 1, 1, QT_LEFT) self.gridlayout_eqp.addWidget(self.label_message_equipement, 2, 0, 1, 2, QT_LEFT) self.lcdnumber_ping_eqp.setMaximumSize(QSize(75, 25)) self.lcdnumber_ping_eqp.setFixedSize(QLCD_SIZE2) self.gridlayout_eqp.addWidget(self.lcdnumber_ping_eqp, 2, 1, 1, 1, QT_RIGHT) self.label_binaire.setFixedSize(100, 20) self.checkbox_equipement.stateChanged.connect(self.oncheckbox_toggled) self.layout_binaire.addWidget(self.label_binaire) self.layout_binaire.addWidget(self.checkbox_equipement) self.gridlayout_eqp.addLayout(self.layout_binaire, 0, 1, 1, 1, QT_CENTER) self.label_command.setText("None") self.label_command.setFixedSize(75, 30) self.label_command.setReadOnly(True) self.label_command.setAlignment(QT_CENTER) self.gridlayout_eqp.addWidget(self.label_command, 1, 1, 1, 1, QT_RIGHT) self.label_last_command.setText("Dern. Cmd:") self.gridlayout_eqp.addWidget(self.label_last_command, 1, 0, 1, 1, QT_LEFT) def updt_cmd(self, state): """Met à jour le timestamp de dernière commande et la dernière commande""" anr.Binaire.updt_cmd(self, state) self.label_command.setText(str(state)) def set_state(self, valeur): """Change la valeur Entrée: - valeur (float)""" anr.Binaire.set_state(self, valeur) self.updated_outside = True self.checkbox_equipement.setChecked(int(valeur)) self.updated_outside = False #calcul et mise à jour du ping def update_ping(self): """Mise à jour du ping de l'équipement""" self.ping = round(abs(time.time() - self.last_updt), 1) self.lcdnumber_ping_eqp.display(format(self.ping)) @pyqtSlot() def oncheckbox_toggled(self): """ Affiche et renvoie vers backend la dernière commande d'un actionneur binaire""" if not self.updated_outside: state = 1 if self.checkbox_equipement.isChecked() else 0 self.backend.sendeqpcmd(self.parent_robot.rid, self.nom, state) self.updt_cmd(state)
class MainCode(QWidget): """MainCode of this program""" def __init__(self, parent=None): super(MainCode, self).__init__(parent) self.initUI() def initUI(self): """constructor""" self.main_hbox = QtWidgets.QHBoxLayout() self.main_vbox = QtWidgets.QVBoxLayout() self.main_elements_created = False self.test_elements_created = False self.result_elements_created = False self.settigs_elements_created = False self.square_color_before_change = QtCore.Qt.white self.square_color_after_change = QtCore.Qt.red self.music_player = QtMultimedia.QMediaPlayer() self.resize(1024, 768) self.setWindowTitle('Оценка скорости реакции') self.main_hbox.addLayout(self.main_vbox) self.setLayout(self.main_hbox) self.main_stage() self.show() def create_test_stage_elements(self): self.number_indicator = QLCDNumber(self) self.number_indicator.setDigitCount(5) self.number_indicator.display("00:00") self.number_indicator.setFixedSize(400, 100) self.timer = QtCore.QTimer() self.timer.setInterval(10) self.timer.timeout.connect(self.display) self.vbox_for_test_elements.addWidget(self.number_indicator, alignment=QtCore.Qt.AlignHCenter) self.vbox_for_test_elements.addStretch(1) self.btn_square = QtWidgets.QPushButton(' ', self) self.btn_square.setFixedSize(500, 500) self.btn_square.setShortcut("Space") palette = self.palette() palette.setColor(QtGui.QPalette.Button, self.square_color_before_change) self.btn_square.setPalette(palette) self.btn_square.update() self.vbox_for_test_elements.addWidget(self.btn_square, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter) self.vbox_for_test_elements.addStretch(1) self.btn_start_stop = QtWidgets.QPushButton('Старт') self.btn_start_stop.setFixedSize(300, 50) self.btn_start_stop.clicked.connect(self.start_test) self.vbox_for_test_elements.addWidget(self.btn_start_stop, alignment=QtCore.Qt.AlignBottom | QtCore.Qt.AlignHCenter) self.main_elements_created = True self.main_vbox.addLayout(self.vbox_for_test_elements) def show_test_stage_elements(self): self.number_indicator.show() self.vbox_for_test_elements.addWidget(self.number_indicator, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter) self.vbox_for_test_elements.addStretch(1) self.vbox_for_test_elements.addWidget(self.btn_square, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter) palette = self.palette() palette.setColor(QtGui.QPalette.Button, self.square_color_before_change) self.btn_square.setPalette(palette) self.btn_square.update() self.btn_square.show() self.vbox_for_test_elements.addStretch(1) self.vbox_for_test_elements.addWidget(self.btn_start_stop, alignment=QtCore.Qt.AlignBottom | QtCore.Qt.AlignHCenter) self.btn_start_stop.show() self.main_vbox.addLayout(self.vbox_for_test_elements) def go_to_test_stage(self): """create buttons and open test window""" self.ms = 0 self.sec = 0 self.result_dict = {} self.list_of_reaction_times = [] self.list_of_dicts_reaction_times_num_of_try = [] self.list_of_falstarts = [] self.vbox_for_test_elements = QtWidgets.QVBoxLayout() if self.test_elements_created == True: self.show_test_stage_elements() elif self.test_elements_created == False: self.create_test_stage_elements() def random_second(self, start, end): """generate random time in ms""" random_sec = start + random.randrange((end - start) * 10) / 10 return random_sec def btn_square_click(self): """Останавливает таймер, обовляет счётчик попыток, вносит время реакции в список, обновляет цвет квадрата, БЕЗ звука""" self.timer.stop() self.count_of_try += 1 if self.count_of_try == 100: self.stop_test_and_go_to_result_stage() if self.ms != 0: self.list_of_reaction_times.append( float(str(self.sec) + "." + str(self.ms))) self.list_of_dicts_reaction_times_num_of_try.append( {self.count_of_try: float(str(self.sec) + "." + str(self.ms))}) self.test_start_timer() else: self.list_of_falstarts.append(self.count_of_try) palette = self.palette() palette.setColor(QtGui.QPalette.Button, self.square_color_before_change) self.btn_square.setPalette(palette) self.btn_square.update() self.sec = 0 self.ms = 0 self.number_indicator.display("%02d:%02d" % (self.sec, self.ms)) def btn_square_click_with_sound(self): """Останавливает таймер, обовляет счётчик попыток, вносит время реакции в список, обновляет цвет квадрата, СО звуком""" self.timer.stop() self.count_of_try += 1 if self.count_of_try == 100: self.stop_test_and_go_to_result_stage() if self.ms != 0: self.list_of_reaction_times.append( float(str(self.sec) + "." + str(self.ms))) self.list_of_dicts_reaction_times_num_of_try.append( {self.count_of_try: float(str(self.sec) + "." + str(self.ms))}) self.test_start_timer_with_sonund() else: self.list_of_falstarts.append(self.count_of_try) palette = self.palette() palette.setColor(QtGui.QPalette.Button, self.square_color_before_change) self.btn_square.setPalette(palette) self.btn_square.update() self.sec = 0 self.ms = 0 self.number_indicator.display("%02d:%02d" % (self.sec, self.ms)) def start_timer(self): """Вызывает срабатывание таймера """ self.timer.start() def change_color_start_test_timer(self): """Запускает таймер, меняет цвет квадрата, без звука""" self.start_timer() palette = self.palette() palette.setColor(QtGui.QPalette.Button, self.square_color_after_change) self.btn_square.setPalette(palette) self.btn_square.update() def change_color_start_test_timer_with_sound(self): """Запускает таймер, меняет цвет квадрата, запускает срабатывание звука""" self.start_timer() palette = self.palette() palette.setColor(QtGui.QPalette.Button, self.square_color_after_change) self.btn_square.setPalette(palette) self.btn_square.update() self.music_player.play() def test_start_timer(self): """Запускает внутренний таймер до смены цвета""" QtCore.QTimer.singleShot((self.random_second(0.5, 3.0) * 1000), self.change_color_start_test_timer) def test_start_timer_with_sonund(self): """Запускает внутренний таймер до смены цвета и запуска звука""" QtCore.QTimer.singleShot((self.random_second(0.5, 3.0) * 1000), self.change_color_start_test_timer_with_sound) def start_test(self): """Выбирает какой метод запустить: со звуком или без звука, меняет название и функцию кнопки'старт', объявляет счётчик попыток""" try: if self.sound_checkbox.checkState() == 2: self.test_start_timer_with_sonund() self.btn_square.clicked.connect( self.btn_square_click_with_sound) elif self.sound_checkbox.checkState() == 0: self.test_start_timer() self.btn_square.clicked.connect(self.btn_square_click) except: self.test_start_timer() self.btn_square.clicked.connect(self.btn_square_click) self.count_of_try = 0 self.btn_start_stop.setText('Стоп') self.btn_start_stop.clicked.disconnect() self.btn_start_stop.clicked.connect( self.stop_test_and_go_to_result_stage) self.btn_start_stop.setShortcut("Esc") def stop_test_and_go_to_result_stage(self): self.timer.stop() self.number_indicator.hide() self.btn_square.hide() self.btn_start_stop.hide() self.main_vbox.removeWidget(self.number_indicator) self.main_vbox.removeWidget(self.btn_square) self.main_vbox.removeWidget(self.btn_start_stop) self.clear_the_main_box_from_stretch_and_space() self.go_to_result_stage() def rounding_func(self, numObj, digits=3): """Обрезает знаки за запятой""" return f"{numObj:.{digits}f}" def back_to_main_window(self): """Скрывает все элементы из окна с результатами и возвращается на главное окно""" self.table.hide() self.graph_of_results.hide() self.btn_go_to_main_menu.hide() self.btn_import.hide() self.clear_the_main_box_from_stretch_and_space() self.main_stage() def fill_in_the_table(self): list_of_table_column_names = [ 'Количество попыток', 'Лучший результат', 'Номера попыток с лучшим результатом', 'Хуший результат', 'Номера попыток с худшим результатом', 'Количество фальстартов', 'Номера попыток с фальстартами', 'Средний результат' ] for element in list_of_table_column_names: column_name = QtGui.QStandardItem(element) self.model.setItem(0, self.counter_for_tries_for_table, column_name) self.counter_for_tries_for_table += 1 self.table.resizeRowsToContents() self.model.setItem(1, 0, QtGui.QStandardItem(str(self.count_of_try))) self.model.setItem( 1, 1, QtGui.QStandardItem(str(min(self.list_of_reaction_times)))) list_of_best_tries = [] for elem in self.list_of_dicts_reaction_times_num_of_try: if elem[list(elem)[0]] == min(self.list_of_reaction_times): list_of_best_tries.append(list(elem)[0]) string_of_best_tries = '' for num in list_of_best_tries: string_of_best_tries += str(num) + ', ' self.model.setItem(1, 2, QtGui.QStandardItem(str(string_of_best_tries))) self.model.setItem( 1, 3, QtGui.QStandardItem(str(max(self.list_of_reaction_times)))) list_of_worst_tries = [] for elem in self.list_of_dicts_reaction_times_num_of_try: if elem[list(elem)[0]] == max(self.list_of_reaction_times): list_of_worst_tries.append(list(elem)[0]) string_of_worst_tries = '' for num in list_of_worst_tries: string_of_worst_tries += str(num) + ', ' self.model.setItem(1, 4, QtGui.QStandardItem(str(string_of_worst_tries))) self.model.setItem( 1, 5, QtGui.QStandardItem(str(len(self.list_of_falstarts)))) numbers_of_falstarts = '' for num in self.list_of_falstarts: numbers_of_falstarts += str(num) + ', ' self.model.setItem(1, 6, QtGui.QStandardItem(str(len(numbers_of_falstarts)))) var_for_average_result = 0 for elem in self.list_of_dicts_reaction_times_num_of_try: var_for_average_result += elem[list(elem)[0]] average_result = var_for_average_result / len( self.list_of_dicts_reaction_times_num_of_try) self.model.setItem( 1, 7, QtGui.QStandardItem(str(self.rounding_func(average_result)))) def show_result_elements(self): self.table.show() self.result_stage_vbox.addWidget(self.table, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter) self.result_stage_vbox.addStretch(1) #Создаёт график потому что это не Qt элемент и ему нужно перерисовываться self.graph_of_results = PlotCanvas( self, width=10, height=5, data_for_graph=self.list_of_dicts_reaction_times_num_of_try) self.result_stage_vbox.addWidget(self.graph_of_results, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter) self.result_stage_vbox.addStretch(1) self.btn_go_to_main_menu.show() self.result_stage_hbox.addWidget(self.btn_go_to_main_menu) self.result_stage_hbox.addStretch(1) self.btn_import.show() self.result_stage_hbox.addWidget(self.btn_import) self.result_stage_hbox.addStretch(1) self.result_stage_hbox.addSpacing(200) self.result_stage_vbox.addLayout(self.result_stage_hbox) def create_result_elements(self): self.table = QtWidgets.QTableView() self.table.setFixedSize(819, 138) self.model = QtGui.QStandardItemModel(2, 8) self.table.setModel(self.model) self.result_stage_vbox.addWidget(self.table, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter) self.result_stage_vbox.addStretch(1) self.graph_of_results = PlotCanvas( self, width=10, height=5, data_for_graph=self.list_of_dicts_reaction_times_num_of_try) self.result_stage_vbox.addWidget(self.graph_of_results, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter) self.result_stage_vbox.addStretch(1) self.btn_go_to_main_menu = QtWidgets.QPushButton( 'Вернуться на главное меню') self.btn_go_to_main_menu.setFixedSize(200, 50) self.btn_go_to_main_menu.clicked.connect(self.back_to_main_window) self.result_stage_hbox.addWidget(self.btn_go_to_main_menu) self.result_stage_hbox.addStretch(1) self.btn_import = QtWidgets.QPushButton('Импорт') self.btn_import.setFixedSize(100, 50) self.btn_import.clicked.connect(self.create_csv_table) self.result_stage_hbox.addWidget(self.btn_import) self.result_stage_hbox.addStretch(1) self.result_stage_hbox.addSpacing(200) self.result_stage_vbox.addLayout(self.result_stage_hbox) def go_to_result_stage(self): """Создаёт финальное окно результатов""" if bool(self.list_of_reaction_times) == False: self.main_stage() return self.counter_for_tries_for_table = 0 self.result_stage_vbox = QtWidgets.QVBoxLayout() self.result_stage_hbox = QtWidgets.QHBoxLayout() if self.result_elements_created == True: self.show_result_elements() elif self.result_elements_created == False: self.create_result_elements() self.fill_in_the_table() self.main_vbox.addLayout(self.result_stage_vbox) def display(self): """Отвечает за обновление дисплея таймера""" self.number_indicator.display("%02d:%02d" % (self.sec, self.ms)) if self.ms != 99: self.ms += 1 else: self.ms = 0 if self.sec != 59: self.sec += 1 def background_color_window(self): """Создаёт окно и позволяет выбрать и обновить цвет фона""" background_color = QtWidgets.QColorDialog.getColor( parent=self, title='Выбор цвета фона') if background_color.isValid(): palette = self.palette() palette.setColor(QtGui.QPalette.Normal, QtGui.QPalette.Background, background_color) palette.setColor(QtGui.QPalette.Inactive, QtGui.QPalette.Background, background_color) self.setPalette(palette) def square_color_window(self): """Создаёт окно и позволяет выбрать и обновить цвет квадрата""" self.square_color_before_change = QtWidgets.QColorDialog.getColor( parent=self, title='Выбор цвета квадрата') if self.square_color_before_change.isValid(): palette = self.palette() palette.setColor(QtGui.QPalette.Button, self.square_color_before_change) self.btn_square.setPalette(palette) self.btn_square.update() def square_after_change_color_window(self): """Создаёт окно и позволяет выбрать и обновить цвет квадрата после смены цвета""" color_after_change = QtWidgets.QColorDialog.getColor( parent=self, title='Выбор цвета квадрата') if color_after_change.isValid(): self.square_color_after_change = color_after_change palette = self.palette() palette.setColor(QtGui.QPalette.Button, self.square_color_after_change) self.btn_square.setPalette(palette) self.btn_square.update() def change_square_settings_color_before(self): """Красит квадрат в цвет до смены цвета""" palette = self.palette() palette.setColor(QtGui.QPalette.Button, self.square_color_before_change) self.btn_square.setPalette(palette) self.btn_square.update() def change_square_settings_color_after(self): """Красит квадрат в цвет после смены цвета""" palette = self.palette() palette.setColor(QtGui.QPalette.Button, self.square_color_after_change) self.btn_square.setPalette(palette) self.btn_square.update() def open_music_file(self): """Открывает окно для выбора музыкального файла""" file = QtWidgets.QFileDialog.getOpenFileUrl( parent=self, caption="Выберите звуковой файл", filter="Звуковые файлы (*.mp3 *.ac3)") self.music_player.setMedia(QtMultimedia.QMediaContent(file[0])) if self.btn_play_music.isHidden(): self.btn_play_music.show() with open( 'config.json', 'w', encoding="utf-8", ) as config_file: config_file.write(file[0].toString()) def go_to_main_stage_from_setting(self): self.btn_go_back.hide() self.btn_background_color_settings.hide() self.btn_square_color_settings.hide() self.btn_square.hide() self.sound_option_text.hide() self.sound_checkbox.hide() self.btn_square_after_change_color_settings.hide() self.btn_square_color_before_change_color.hide() self.btn_square_color_after_change_color.hide() self.btn_open_music.hide() self.label_music_status.hide() self.btn_play_music.hide() self.main_stage() def show_settings_elements(self): self.btn_go_back.show() self.settings_hbox_1.addWidget(self.btn_go_back, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft) self.btn_background_color_settings.show() self.settings_hbox_1.addWidget(self.btn_background_color_settings, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft) self.btn_square_color_settings.show() self.settings_hbox_1.addWidget(self.btn_square_color_settings, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft) self.btn_square_after_change_color_settings.show() self.settings_hbox_1.addWidget( self.btn_square_after_change_color_settings, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft) self.settings_hbox_1.addStretch(1) self.btn_square_color_before_change_color.show() self.settings_hbox_1.addWidget( self.btn_square_color_before_change_color, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignRight) self.btn_square_color_after_change_color.show() self.settings_hbox_1.addWidget( self.btn_square_color_after_change_color, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignRight) self.settings_vbox_1.addLayout(self.settings_hbox_1) self.btn_square.show() self.settings_vbox_1.addStretch(1) self.settings_vbox_1.addWidget(self.btn_square, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter) self.settings_vbox_1.addStretch(1) self.btn_open_music.show() self.settings_hbox_2.addWidget(self.btn_open_music) self.settings_hbox_2.addStretch(1) self.label_music_status.show() self.settings_hbox_2.addWidget(self.label_music_status) self.settings_hbox_2.addStretch(1) self.btn_play_music.show() self.settings_hbox_2.addWidget(self.btn_play_music) self.settings_hbox_2.addStretch(1) self.sound_option_text.show() self.settings_hbox_2.addWidget(self.sound_option_text) self.sound_checkbox.show() self.settings_hbox_2.addWidget(self.sound_checkbox) self.settings_hbox_2.addStretch(1) self.settings_vbox_1.addLayout(self.settings_hbox_2) self.main_vbox.addLayout(self.settings_vbox_1) def create_settings_elemens(self): self.btn_go_back = QtWidgets.QPushButton('Назад', self) self.btn_go_back.setFixedSize(50, 50) self.btn_go_back.clicked.connect(self.go_to_main_stage_from_setting) self.settings_hbox_1.addWidget(self.btn_go_back, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft) self.btn_background_color_settings = QtWidgets.QPushButton( 'Цвет фона', self) self.btn_background_color_settings.setFixedSize(100, 50) self.btn_background_color_settings.clicked.connect( self.background_color_window) self.settings_hbox_1.addWidget(self.btn_background_color_settings, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft) self.btn_square_color_settings = QtWidgets.QPushButton( 'Цвет квадрата до смены цвета', self) self.btn_square_color_settings.setFixedSize(250, 50) self.btn_square_color_settings.clicked.connect( self.square_color_window) self.settings_hbox_1.addWidget(self.btn_square_color_settings, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft) self.btn_square_after_change_color_settings = QtWidgets.QPushButton( 'Цвет квадрата после смены цвета', self) self.btn_square_after_change_color_settings.setFixedSize(250, 50) self.btn_square_after_change_color_settings.clicked.connect( self.square_after_change_color_window) self.settings_hbox_1.addWidget( self.btn_square_after_change_color_settings, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft) self.settings_hbox_1.addStretch(1) self.btn_square_color_before_change_color = QtWidgets.QPushButton( 'Квадрат до смены цвета', self) self.btn_square_color_before_change_color.setFixedSize(200, 50) self.btn_square_color_before_change_color.clicked.connect( self.change_square_settings_color_before) self.settings_hbox_1.addWidget( self.btn_square_color_before_change_color, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignRight) self.btn_square_color_after_change_color = QtWidgets.QPushButton( 'Квадрат после смены цвета', self) self.btn_square_color_after_change_color.setFixedSize(200, 50) self.btn_square_color_after_change_color.clicked.connect( self.change_square_settings_color_after) self.settings_hbox_1.addWidget( self.btn_square_color_after_change_color, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignRight) self.settings_vbox_1.addLayout(self.settings_hbox_1) self.btn_square = QtWidgets.QPushButton(' ', self) self.btn_square.setAutoFillBackground(True) self.btn_square.setFixedSize( 500, 500) # установить 2 переменные для настроек размера palette = self.palette() palette.setColor(QtGui.QPalette.Button, self.square_color_before_change) self.btn_square.setPalette(palette) self.btn_square.update() self.settings_vbox_1.addStretch(1) self.settings_vbox_1.addWidget(self.btn_square, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter) self.settings_vbox_1.addStretch(1) self.btn_open_music = QtWidgets.QPushButton("&Открыть файл...") self.btn_open_music.clicked.connect(self.open_music_file) self.settings_hbox_2.addWidget(self.btn_open_music) self.settings_hbox_2.addStretch(1) self.label_music_status = QtWidgets.QLabel('') self.label_music_status.hide() self.settings_hbox_2.addWidget(self.label_music_status) self.settings_hbox_2.addStretch(1) self.btn_play_music = QtWidgets.QPushButton('Прослушать') self.btn_play_music.clicked.connect(self.music_player.play) self.btn_play_music.hide() self.settings_hbox_2.addWidget(self.btn_play_music) self.settings_hbox_2.addStretch(1) self.sound_option_text = QtWidgets.QLabel("Наличие звукового сигнала") font_obj_for_label = QtGui.QFont('Segoe UI', pointSize=30) self.sound_option_text.setFont(font_obj_for_label) self.sound_option_text.show() self.settings_hbox_2.addWidget(self.sound_option_text) self.sound_checkbox = QtWidgets.QCheckBox(self) self.settings_hbox_2.addWidget(self.sound_checkbox) self.settings_hbox_2.addStretch(1) self.settings_vbox_1.addLayout(self.settings_hbox_2) self.main_vbox.addLayout(self.settings_vbox_1) self.settigs_elements_created = True def go_to_settings_stage(self): """Открывает окно настроек, создаёт все кнопки и всё там делает""" self.settings_hbox_1 = QtWidgets.QHBoxLayout() self.settings_vbox_1 = QtWidgets.QVBoxLayout() self.settings_hbox_2 = QtWidgets.QHBoxLayout() if self.settigs_elements_created == True: self.show_settings_elements() elif self.settigs_elements_created == False: self.create_settings_elemens() try: with open( 'config.json', 'r', encoding="utf-8", ) as config_file: self.path_to_the_installed_music = config_file.read() self.music_player.setMedia( QtMultimedia.QMediaContent( QtCore.QUrl(self.path_to_the_installed_music))) self.label_music_status.setText('Звук установлен') self.label_music_status.show() self.btn_play_music.show() except: self.label_music_status.setText('Звук не установлен') self.label_music_status.show() def clear_the_main_box_from_stretch_and_space(self): for i in range(self.main_vbox.count()): layout_item = self.main_vbox.itemAt(i) print(layout_item) if layout_item.layout() is not None: self.main_vbox.removeItem(layout_item) def go_to_test_stage_from_main_stage(self): self.title.hide() self.btn_start_test.hide() self.btn_settings.hide() self.main_vbox.removeWidget(self.title) self.main_vbox.removeWidget(self.btn_start_test) self.main_vbox.removeWidget(self.btn_settings) self.clear_the_main_box_from_stretch_and_space() self.go_to_test_stage() def go_to_settings_stage_from_main_stage(self): self.title.hide() self.btn_start_test.hide() self.btn_settings.hide() self.main_vbox.removeWidget(self.title) self.main_vbox.removeWidget(self.btn_start_test) self.main_vbox.removeWidget(self.btn_settings) self.clear_the_main_box_from_stretch_and_space() self.go_to_settings_stage() def create_main_stage_elements(self): self.title = QtWidgets.QLabel("Оценка скорости реакции", self) font_obj_for_label = QtGui.QFont('Segoe UI', pointSize=50) self.title.setFont(font_obj_for_label) self.main_vbox.addWidget(self.title, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter) self.btn_start_test = QtWidgets.QPushButton('Тест', self) self.btn_start_test.setFixedSize(300, 50) self.btn_start_test.clicked.connect( self.go_to_test_stage_from_main_stage) self.main_vbox.addWidget(self.btn_start_test, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignCenter) self.btn_settings = QtWidgets.QPushButton('Настройки', self) self.btn_settings.setFixedSize(300, 50) self.btn_settings.clicked.connect( self.go_to_settings_stage_from_main_stage) self.main_vbox.addWidget(self.btn_settings, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignCenter) self.settings_elements_created = True def show_main_stage_elements(self): self.title.show() self.main_vbox.addWidget(self.title, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter) self.btn_start_test.show() self.main_vbox.addWidget(self.btn_start_test, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignCenter) self.btn_settings.show() self.main_vbox.addWidget(self.btn_settings, alignment=QtCore.Qt.AlignTop | QtCore.Qt.AlignCenter) def main_stage(self): """Создаёт главное окно""" self.clear_the_main_box_from_stretch_and_space() if self.main_elements_created == True: self.show_main_stage_elements() elif self.main_elements_created == False: self.create_main_stage_elements() def create_csv_table(self): with open('result_table.csv', "w", newline='') as csv_file: writer = csv.writer(csv_file, delimiter=',') count_num_and_try_time = [] for element in self.list_of_dicts_reaction_times_num_of_try: count_num_and_try_time.append( [list(element)[0], element[list(element)[0]]]) for element in count_num_and_try_time: writer.writerow(element)
class DedeNimeur(QMainWindow): def __init__(self): super(DedeNimeur, self).__init__() self.statusBar() self.size, self.height, self.width, self.mines = 30, 10, 10, 10 self.lcd = QLCDNumber() self.lcd.setFixedSize(300, 60) self.board = Board(self.height, self.width, self.mines, self.size) self.timer = QBasicTimer() self.real_timer = QElapsedTimer() vbox = QVBoxLayout() vbox.addWidget(self.lcd) vbox.addWidget(self.board) central = QWidget() central.setLayout(vbox) self.setCentralWidget(central) start = QAction('Start', self) start.setStatusTip('Start') start.setShortcut('Ctrl+N') start.triggered.connect(self.init) exit = QAction('Exit', self) exit.setStatusTip('Exit') exit.setShortcut('Ctrl+Q') exit.triggered.connect(qApp.quit) height = QAction('Height', self) height.setStatusTip('Set board width') height.triggered.connect(self.set_height) width = QAction('Width', self) width.setStatusTip('Set board height') width.triggered.connect(self.set_width) mines = QAction('Mines', self) mines.setStatusTip('Set board mines') mines.triggered.connect(self.set_mines) size = QAction('Size', self) size.setStatusTip('Set button size') size.triggered.connect(self.set_size) toolbar = self.addToolBar('Toolbar') toolbar.addAction(start) toolbar.addAction(width) toolbar.addAction(height) toolbar.addAction(mines) toolbar.addAction(size) toolbar.addAction(exit) self.setWindowTitle(u'DédéNimeur') self.show() def init(self): if self.mines < self.height * self.width: self.board.height = self.height self.board.width = self.width self.board.mines = self.mines self.board.size = self.size self.board.init() else: QMessageBox.question(self, 'NOPE', u"Va falloir spécifier un truc cohérent…", QMessageBox.Ok) def set_height(self): text, ok = QInputDialog.getText(self, 'Settings', 'height') if ok: self.height = int(text) self.init() def set_width(self): text, ok = QInputDialog.getText(self, 'Settings', 'width') if ok: self.width = int(text) self.init() def set_mines(self): text, ok = QInputDialog.getText(self, 'Settings', 'mines') if ok: self.mines = int(text) self.init() def set_size(self): text, ok = QInputDialog.getText(self, 'Settings', 'size') if ok: self.size = int(text) self.init() def start_timers(self): self.timer.start(100, self) self.real_timer.start() self.lcd.display(int(self.real_timer.elapsed() / 1000)) def stop_timers(self): self.timer.stop() return self.real_timer.elapsed() def timerEvent(self, e): self.lcd.display(int(self.real_timer.elapsed() / 1000))
class Tetrixs(QWidget): def __init__(self): super(Tetrixs, self).__init__() self.initUI() def initUI(self): #窗口大小固定 size = self.centerRect(tetrixsWidth, tetrixsHeight) self.setGeometry(size) self.setWindowTitle('Tetrixs') #设置背景色 self.setStyleSheet(mainWindowColor) #LCD和Button self.levelNumber = QLCDNumber(self) self.scoreNumber = QLCDNumber(self) #设置初始值 self.levelNumber.display(0) self.scoreNumber.display(0) self.pauseButton = QPushButton('PAUSE', self) self.startButton = QPushButton('START', self) #设置两个按钮无焦点 self.pauseButton.setFocusPolicy(Qt.NoFocus) self.startButton.setFocusPolicy(Qt.NoFocus) #self.setFocusPolicy(Qt.StrongFocus) #self.startButton.set self.levelNumber.setFixedSize(150, 100) self.scoreNumber.setFixedSize(150, 100) self.pauseButton.setFixedSize(150, 100) self.startButton.setFixedSize(150, 100) self.levelNumber.setStyleSheet(lcdNumberColor) self.scoreNumber.setStyleSheet(lcdNumberColor) self.pauseButton.setStyleSheet(buttonColor) self.startButton.setStyleSheet(buttonColor) ##LCD和Button绑定action函数 self.startButton.clicked.connect(self.startButtonAction) self.pauseButton.clicked.connect(self.pauseButtonAction) vLayout = QVBoxLayout() vLayout.addWidget(self.levelNumber) vLayout.addWidget(self.scoreNumber) vLayout.addWidget(self.pauseButton) vLayout.addWidget(self.startButton) #画布 self.canvas = Canvas() self.canvas.setFixedSize(500, 800) self.canvas.getScoreSignal.connect(self.getScoreAction) self.canvas.gameOverSignal.connect(self.gameOverAction) hLayout = QHBoxLayout() hLayout.addWidget(self.canvas) hLayout.addLayout(vLayout) self.setLayout(hLayout) self.setFixedSize(tetrixsWidth, tetrixsHeight) self.show() def centerRect(self, width, height): screen = QGuiApplication.primaryScreen() screenWidth = screen.geometry().width() screenHeight = screen.geometry().height() centerWidth, centerHeight = screenWidth // 2, screenHeight // 2 startWidth, startHeight = centerWidth - width // 2, centerHeight - height // 2 return QRect(startWidth , startHeight, width, height) def keyPressEvent(self, event): #向左旋转 if event.key() == Qt.Key_Up: self.canvas.rotateLeft() #向右旋转 if event.key() == Qt.Key_Down: self.canvas.rotateRight() #向左移动 if event.key() == Qt.Key_Left: self.canvas.moveLeft() #向右移动 if event.key() == Qt.Key_Right: self.canvas.moveRight() if event.key() == Qt.Key_Space: self.canvas.downDirect() def startButtonAction(self): #设置初始值 self.levelNumber.display(0) self.scoreNumber.display(0) self.canvas.start() def pauseButtonAction(self): self.canvas.pause() if self.pauseButton.text() == "PAUSE": self.pauseButton.setText("CONTINUE") else: self.pauseButton.setText("PAUSE") def getScoreAction(self, score): QApplication.beep() value = self.scoreNumber.intValue() newValue = value + score self.scoreNumber.display(newValue) #更新speed if value / levelStep != newValue / levelStep: self.levelNumber.display(newValue / levelStep) self.canvas.speed *= percent def gameOverAction(self): self.msg() def msg(self): reply = QMessageBox.information(self, "Tetrixs", "GameOver", QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: self.canvas.start() if reply == QMessageBox.No: app = QApplication(sys.argv) app.exit(0)
class DedeNimeur(QMainWindow): def __init__(self): super(DedeNimeur, self).__init__() self.statusBar() self.size, self.height, self.width, self.mines = 30, 10, 10, 10 self.lcd = QLCDNumber() self.lcd.setFixedSize(300, 60) self.board = Board(self.height, self.width, self.mines, self.size) self.timer = QBasicTimer() self.real_timer = QElapsedTimer() vbox = QVBoxLayout() vbox.addWidget(self.lcd) vbox.addWidget(self.board) central = QWidget() central.setLayout(vbox) self.setCentralWidget(central) start = QAction('Start', self) start.setStatusTip('Start') start.setShortcut('Ctrl+N') start.triggered.connect(self.init) exit = QAction('Exit', self) exit.setStatusTip('Exit') exit.setShortcut('Ctrl+Q') exit.triggered.connect(qApp.quit) height = QAction('Height', self) height.setStatusTip('Set board width') height.triggered.connect(self.set_height) width = QAction('Width', self) width.setStatusTip('Set board height') width.triggered.connect(self.set_width) mines = QAction('Mines', self) mines.setStatusTip('Set board mines') mines.triggered.connect(self.set_mines) size = QAction('Size', self) size.setStatusTip('Set button size') size.triggered.connect(self.set_size) toolbar = self.addToolBar('Toolbar') toolbar.addAction(start) toolbar.addAction(width) toolbar.addAction(height) toolbar.addAction(mines) toolbar.addAction(size) toolbar.addAction(exit) self.setWindowTitle(u'DédéNimeur') self.show() def init(self): if self.mines < self.height * self.width: self.board.height = self.height self.board.width = self.width self.board.mines = self.mines self.board.size = self.size self.board.init() else: QMessageBox.question(self, 'NOPE', u"Va falloir spécifier un truc cohérent…", QMessageBox.Ok) def set_height(self): text, ok = QInputDialog.getText(self, 'Settings', 'height') if ok: self.height = int(text) self.init() def set_width(self): text, ok = QInputDialog.getText(self, 'Settings', 'width') if ok: self.width = int(text) self.init() def set_mines(self): text, ok = QInputDialog.getText(self, 'Settings', 'mines') if ok: self.mines = int(text) self.init() def set_size(self): text, ok = QInputDialog.getText(self, 'Settings', 'size') if ok: self.size = int(text) self.init() def start_timers(self): self.timer.start(100, self) self.real_timer.start() self.lcd.display(int(self.real_timer.elapsed() / 1000)) def stop_timers(self): self.timer.stop() return self.real_timer.elapsed() def timerEvent(self, e): self.lcd.display(int(self.real_timer.elapsed() / 1000))
class GamePlayerWidget(QGroupBox): def __init__(self, nick, colour=None, parent=None): super(GamePlayerWidget, self).__init__(parent) self.player = nick self.pcolour = colour self.initUI() def initUI(self): # self.setMinimumWidth(300) self.mainLayout = QHBoxLayout(self) # self.mainLayout.addStretch() self.scoreLCD = QLCDNumber(self) self.scoreLCD.setSegmentStyle(QLCDNumber.Flat) self.mainLayout.addWidget(self.scoreLCD) self.scoreLCD.setNumDigits(3) self.scoreLCD.setFixedSize(100, 60) self.scoreLCD.display(0) css = "QLCDNumber {{ color:rgb({},{},{});}}" self.scoreLCD.setStyleSheet(css.format(self.pcolour.red(), self.pcolour.green(), self.pcolour.blue())) self.nameLabel = QLabel(self) self.nameLabel.setText(self.player) sh = ("QLabel {{ font-size: 32px; font-weight: " "bold; color:rgb({},{},{});}}") self.nameLabel.setStyleSheet(sh.format(self.pcolour.red(), self.pcolour.green(), self.pcolour.blue())) self.mainLayout.addWidget(self.nameLabel) self.dealerPixmap = QtGui.QPixmap('icons/cards.png') self.nonDealerPixmap = QtGui.QPixmap() self.winnerPixmap = QtGui.QPixmap('icons/winner.png') self.iconlabel = IconLabel(self) self.iconlabel.setFixedSize(50, 50) self.iconlabel.setScaledContents(True) self.mainLayout.insertWidget(0, self.iconlabel) # self.mainLayout.addStretch() self.unsetDealer() def updateDisplay(self, points): if points >= 1000: self.scoreLCD.setNumDigits(4) self.scoreLCD.display(points) def setDealer(self): self.iconlabel.setPixmap(self.dealerPixmap) def unsetDealer(self): self.iconlabel.setPixmap(self.nonDealerPixmap) def setWinner(self): self.iconlabel.setPixmap(self.winnerPixmap) def setColour(self, colour): self.pcolour = colour css = "QLCDNumber {{ color:rgb({},{},{});}}" self.scoreLCD.setStyleSheet(css.format(self.pcolour.red(), self.pcolour.green(), self.pcolour.blue())) sh = ("QLabel {{ font-size: 32px; font-weight: bold; " "color:rgb({},{},{});}}") self.nameLabel.setStyleSheet(sh.format(self.pcolour.red(), self.pcolour.green(), self.pcolour.blue()))
class Klotski(QMainWindow): def __init__(self, maps: Dict[int, KLMap], firstBoard: Optional[int] = None) -> None: QMainWindow.__init__(self) self.klmap = None # type: Optional[KLMap] self.moves = 0 self.move_list = [] # type: List[ Tuple[str, Tuple[int, int]]] self.move_index = -1 self.mini_maps_dict = {} # type: Dict[int, QPixmap] self.levels_by_id = maps self.init_misc_gui() self.board.load_tiles() self.board.sig_move.connect(self.move_tile) self.generate_mini_maps() self.board_chooser = KLBoardChooser( KlMinimapProvider(self.levels_by_id, self.mini_maps_dict), self) self.board_chooser.hide() # needs self.board self.init_menu() self.setWindowTitle("Klotski") self.title_label.setText("Klotski") if firstBoard: self.new_level(self.levels_by_id[int(firstBoard)]) self.move_enabled = True else: self.new_level(self.levels_by_id[ID_SPLASH_SCREEN]) self.move_enabled = False def init_misc_gui(self) -> None: w = QWidget(self) self.setCentralWidget(w) ly = QVBoxLayout() w.setLayout(ly) ly.setSpacing(10) self.title_label = QLabel("Klotski", w) ft = self.title_label.font() ft.setPointSize(20) self.title_label.setFont(ft) self.title_label.setAlignment(Qt.AlignCenter) self.title_label.setSizePolicy( QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)) ly.addWidget(self.title_label) hb = QHBoxLayout() self.board = KLBoard(w) hb.addWidget(self.board) hb.setStretchFactor(self.board, 100) ly.addLayout(hb) # horizontal bottom hbox [ QLabel | QLcdNumber ] hb = QHBoxLayout() # hb.setSpacing( 5 ) # hb.setMargin( 5 ) ml = QLabel("Moves : ", w) ml.setFont(ft) ml.setAlignment(Qt.AlignRight) hb.addWidget(ml) self.move_lcd_nb = QLCDNumber(4, w) self.move_lcd_nb.adjustSize() self.move_lcd_nb.setFixedSize(self.move_lcd_nb.width(), 30) hb.addWidget(self.move_lcd_nb) # hb.setFixedHeight( hb.height() ) ly.addLayout(hb) self.adjustSize() def generate_mini_maps(self) -> None: self.mini_maps_dict = {} for i in self.levels_by_id.keys(): self.mini_maps_dict[i] = self.board.generate_mini_map( self.levels_by_id[i]) def new_level(self, m: KLMap) -> None: '''Display a new map into the main window''' if m.name != NAME_SPLASH_SCREEN: # display the name of the board self.setWindowTitle("Klotski - " + m.name) self.title_label.setText(m.name) else: # display the splash screen self.setWindowTitle("Klotski") self.title_label.setText('') self.klmap = m w = max(m.w * TILE_SIZE + 10 + 40, self.title_label.sizeHint().width() + 20) h = (m.h * TILE_SIZE + 10 + 80 + self.title_label.sizeHint().height() + max(self.move_lcd_nb.sizeHint().height(), self.title_label.sizeHint().height())) center = self.frameGeometry().center() self.resize(w, h) r = self.frameGeometry() r.moveCenter(center) desktop = QApplication.desktop() if r.x() + w > desktop.width() or r.x( ) < 0 or r.y() + h > desktop.height() or r.y() < 0: r.moveCenter(desktop.rect().center()) if r.x() < 0: r.setX(0) if r.y() < 0: r.setY(0) if r.x() + w > desktop.width(): r.setX(0) w = desktop.width() - 20 - r.x() if r.y() + h > desktop.height(): r.setY(0) h = desktop.height() - 20 - r.y() self.move(r.topLeft()) self.resize(w, h) self.reset() def choose_board(self) -> None: self.board_chooser.exec() board_id = self.board_chooser.result() if board_id in self.levels_by_id: self.new_level(self.levels_by_id[board_id]) def init_menu(self) -> None: file_menu = QMenu('Game', self) file_menu.addAction("Boards", self.choose_board, Qt.CTRL + Qt.Key_B) file_menu.addAction("Quit", self.close, Qt.CTRL + Qt.Key_X) # type: ignore file_menu.addAction("About Klotski", self.about) move_menu = QMenu('Moves', self) move_menu.addAction("Reset", self.reset) move_menu.addAction("Undo", self.undo, Qt.CTRL + Qt.Key_U) move_menu.addAction("Redo", self.redo, Qt.CTRL + Qt.Key_R) main_menu = self.menuBar() main_menu.addMenu(file_menu) main_menu.addMenu(move_menu) def set_move_nb(self, m: int) -> None: self.move_lcd_nb.display(m) self.moves = m def move_tile(self, move_info: Tuple[str, Tuple[int, int]]) -> None: pid, delta = move_info if not self.move_enabled: return assert self.klmap self.klmap.move_piece(pid, delta) self.board.move_piece(pid, delta) if self.move_index < 0: self.move_list = [(pid, (0, 0))] self.move_index = 0 self.set_move_nb(self.moves + 1) last_move_pid, last_move = self.move_list[self.move_index] if pid != last_move_pid: self.move_index = self.move_index + 1 self.move_list[self.move_index:] = [(pid, delta)] self.set_move_nb(self.moves + 1) else: self.move_list[self.move_index:] = [ (pid, (last_move[0] + delta[0], last_move[1] + delta[1])) ] if self.klmap.is_game_won(): QMessageBox.information( self, "Congratulation", "Congratulations!!!\nYou completed this level in %d moves" % self.moves) self.move_enabled = False self.klmap.reset() def reset(self) -> None: assert self.klmap self.klmap.reset() self.board.set_map(self.klmap) self.set_move_nb(0) self.move_enabled = True self.move_list = [] self.move_index = -1 def undo(self) -> None: if self.move_index < 0: return if not self.move_enabled: return pid = self.move_list[self.move_index][0] d = reverse_move(self.move_list[self.move_index][1]) assert self.klmap assert self.board self.klmap.move_piece(pid, d) self.board.move_piece(pid, d) self.set_move_nb(self.moves - 1) self.move_index = self.move_index - 1 def redo(self) -> None: if self.move_index + 1 >= len(self.move_list): return if not self.move_enabled: return self.move_index = self.move_index + 1 pid, d = self.move_list[self.move_index] assert self.klmap assert self.board self.klmap.move_piece(pid, d) self.board.move_piece(pid, d) self.set_move_nb(self.moves + 1) def about(self) -> None: QMessageBox.about(self, 'About Klotski', MSG_ABOUT) def print_state(self) -> None: print(self.klmap) print("Move list : ", self.move_list) print("move list index : ", self.move_index)
class Main(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): # number of calls - new game self.CH = 0 # the game timer self.timer = QTimer() self.timer.timeout.connect(self.second_on_LSD) # the number of movies self.num_moves = 0 # the second of game self.second = 0 # number of times the radar-button is pressed self.num_radar = 3 # The initial height of the playing field self.height_area = 9 # The initial width of the playing field self.width_area = 9 # Initial number of mines per field self.num_mines = 10 # loading-flag self.loading = False # Creating a playing field self.createAll() # Creating a playing menu self.createMenu() # Creating playing field components def createAll(self): # New game or loaded from save? if not self.loading: # Filling the field with mines at the beginning of the game self.field = area(self.width_area, self.height_area, self.num_mines) self.loading = False # The central widget self.mainWidget = QWidget(self) self.setCentralWidget(self.mainWidget) # The main layer self.main_vBox = QVBoxLayout(self.mainWidget) # The layer Info-Board self.hBox = QHBoxLayout() # Playing field layer self.grid = QGridLayout() # Top buttons (info-board) self.lcd_left = QLCDNumber() self.lcd_left.setFixedSize(QSize(100, 30)) self.hBox.addWidget(self.lcd_left) self.smile_btn = QPushButton() self.smile_btn.setFixedSize(QSize(40, 40)) self.smile_btn.setIconSize(QSize(40, 40)) self.smile_btn.setIcon(QIcon('./images/smile.png')) self.smile_btn.setFlat(True) # no frame self.smile_btn.clicked.connect(self.newGameAction) self.hBox.addWidget(self.smile_btn) self.lcd_right = QLCDNumber() self.lcd_right.setFixedSize(QSize(100, 30)) self.hBox.addWidget(self.lcd_right) self.main_vBox.addLayout(self.hBox) # Playing field gbox = QGroupBox() gbox.setStyleSheet('background-color: white') # Adding a playing field self.gameArea() self.lcd_left.display(self.num_moves) self.lcd_right.display(self.second) gbox.setLayout(self.grid) self.main_vBox.addWidget(gbox) self.statusBar().showMessage('Go!') self.setLayout(self.main_vBox) # Creating a game menu def createMenu(self): # Menu Events - Game newGame = QAction('New game', self) newGame.setShortcut('Ctrl+N') newGame.triggered.connect(self.newGameAction) newGame.setStatusTip('Start a new game') saveGame = QAction('Save', self) saveGame.setShortcut('Ctrl+S') saveGame.triggered.connect(self.saveGameAction) saveGame.setStatusTip('Save current game') loadGame = QAction('Load', self) loadGame.setShortcut('Ctrl+D') loadGame.triggered.connect(self.loadGameAction) loadGame.setStatusTip('Load current game') statGame = QAction('Statistics', self) statGame.setShortcut('Ctrl+Z') statGame.triggered.connect(self.statGameAction) statGame.setStatusTip('View game statistics') exitGame = QAction('Quit', self) exitGame.setShortcut('Esc') exitGame.triggered.connect(self.close) exitGame.setStatusTip('Quit the game') # Menu Events - Difficulty newbieDiff = QAction('Newbie', self) newbieDiff.triggered.connect(self.newbieDiffAction) newbieDiff.setStatusTip('Field 9х9, 10 mines') amateurDiff = QAction('Amateur', self) amateurDiff.triggered.connect(self.amateurDiffAction) amateurDiff.setStatusTip('Field 16х16, 40 mines') profiDiff = QAction('Professional', self) profiDiff.triggered.connect(self.profiDiffAction) profiDiff.setStatusTip('Field 16х30, 99 mines') specialDiff = QAction('Special...', self) specialDiff.triggered.connect(self.specialDiffAction) specialDiff.setStatusTip('Of your choice') # Menu Events - Help helpHelp = QAction('Rules', self) helpHelp.triggered.connect(self.helpFunc) helpHelp.setStatusTip('Help') aboutHelp = QAction('About the program', self) aboutHelp.triggered.connect(self.aboutFunc) aboutHelp.setStatusTip('About the program') # Menu - Game self.menubar = self.menuBar() self.gameMenu = self.menubar.addMenu('Game') self.gameMenu.addAction(newGame) self.gameMenu.addAction(saveGame) self.gameMenu.addAction(loadGame) self.gameMenu.addAction(statGame) self.gameMenu.addAction(exitGame) # Menu - Difficulty self.diffMenu = self.menubar.addMenu('Difficulty') self.diffMenu.addAction(newbieDiff) self.diffMenu.addAction(amateurDiff) self.diffMenu.addAction(profiDiff) self.diffMenu.addAction(specialDiff) # Menu - Help self.helpMenu = self.menubar.addMenu('Help') self.helpMenu.addAction(helpHelp) self.helpMenu.addAction(aboutHelp) # New game def newGameAction(self): text = 'All gameplay will be reset without saving. Continue?' if self.num_moves > 0 and not self.loading or self.second > 0: self.timerFunc(stop=True) question = QMessageBox.question(self, 'Attention!', text, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if question == QMessageBox.Yes: # Zeroing the timer and the number of moves if "New game" is selected self.timerFunc(reset=True) self.createAll() else: self.timerFunc(pause=True) else: self.createAll() # Gambling field arrangement # Playing field tiles def gameArea(self): # List of game field buttons # to access the state of each button self.list_btns = [] for x in range(self.height_area): row_btns = [] for y in range(self.width_area): value = self.field[x][y] btn = Cell(x, y, value, self.smile_btn, self.timerFunc, self.showMoves, self.checkBTN, self.usedFlag, self.radar, self.changeValue, self) self.grid.addWidget(btn, x, y) row_btns.append(btn) self.list_btns.append(row_btns) # Window geometry if self.CH > 0: self.adjustSize() self.CH += 1 # Change cell value def changeValue(self, value, x, y): self.field[x][y] = value # progress check def checkBTN(self, left, x=None, y=None): # left mouse button if left: self.showMoves() # mine? if self.field[x][y] == 19: self.win = False self.gameOver() elif self.field[x][y] == 10: # List of cells around the pressed button self.open_lst = [] self.openBTN(x, y) # Opening empty cells for k in self.open_lst: k.is_open = True k.update() # right mouse button else: flag_on_mine = 0 for i in range(self.height_area): for j in range(self.width_area): if self.field[i][j] == 29: flag_on_mine += 1 # If all the flags on all mines - victory! if flag_on_mine == self.num_mines: self.win = True self.gameOver() # Count remaining flags def usedFlag(self): flag = 0 for row in self.field: for value in row: if 19 < value < 30: flag += 1 if flag < self.num_mines: self.showMoves() return True else: return False # Game End Check def gameOver(self): self.game_over = True # Win or lose to record statistics if self.win: winner = 'victory' else: winner = 'losing' # Saving game results size = str(self.height_area) + 'x' + str(self.width_area) saveResult(size, str(self.num_mines), str(self.num_moves), str(self.second), winner) self.timerFunc(stop=True) # The result of the dialogue - the end of the game - New game or exit self.new_exit = False dialog = Over(self) dialog.exec_() # Processing the result of the dialog "End of the game" if self.new_exit: # Selected option - new game self.timerFunc(reset=True) self.newGameAction() else: # Closing the main program window, ending the game self.close() # Recursive search for empty cells def openBTN(self, x, y): if self.field[x][y] == 10 or self.field[x][y] == 0: for i in range(x - 1, x + 2): for j in range(y - 1, y + 2): if 0 <= i < self.height_area and 0 <= j < self.width_area and self.field[ i][j] < 9: if self.list_btns[i][j] not in self.open_lst: self.open_lst.append(self.list_btns[i][j]) self.field[i][j] += 10 self.openBTN(i, j) # Method for calculating game time and resetting parameters def timerFunc(self, start=False, stop=False, pause=False, reset=False): if start and self.num_moves == 0: self.timer.start(1000) elif stop: self.timer.stop() stop = False elif pause: self.timer.start() pause = False elif reset: # Zeroing the number of moves self.num_moves = 0 # Zeroing the number of flags on the field self.used_flag = 0 # Setting the radar value if "new game" if self.second > 0 and not self.loading: if self.num_mines <= 10: self.num_radar = 3 elif 10 < self.num_mines <= 40: self.num_radar = 10 elif 40 < self.num_mines: self.num_radar = 15 # Timer reset self.second = 0 # Reset reset reset = False # RADAR method - open (close) cells using RMB def radar(self, open, x=None, y=None): if self.num_radar > 0: if open: self.radar_btn = [] for i in range(x - 1, x + 2): for j in range(y - 1, y + 2): if (0 <= i < self.height_area and 0 <= j < self.width_area and not self.list_btns[i][j].is_open and not self.list_btns[i][j].is_flag): self.radar_btn.append(self.list_btns[i][j]) self.list_btns[i][j].is_open = True self.list_btns[i][j].update() else: for btn in self.radar_btn: btn.is_open = False btn.update() self.num_radar -= 1 # Counting and displaying the number of moves def showMoves(self): self.num_moves += 1 self.lcd_left.display(self.num_moves) # Game time display def second_on_LSD(self): self.second += 1 self.lcd_right.display(self.second) def helpFunc(self): file = open('images/rules.txt') text = file.read() QMessageBox.information(self, 'Reference', text) def aboutFunc(self): QMessageBox.about(self, 'About programm', 'closed beta-vertion') # Save game method def saveGameAction(self): self.saveGameAction = Save(self.second, self.num_moves, self.num_radar, self.width_area, self.field, self) # Saved Game Load Method def loadGameAction(self): self.timerFunc(stop=True) dialog = Load(self) dialog.exec_() if self.loading: self.newGameAction() else: self.timerFunc(pause=True) # View game statistics def statGameAction(self): self.timerFunc(stop=True) dialog = Stat(self) dialog.exec_() self.timerFunc(pause=True) def newbieDiffAction(self): self.height_area = 9 self.width_area = 9 self.num_mines = 10 self.num_radar = 3 self.newGameAction() def amateurDiffAction(self): self.height_area = 16 self.width_area = 16 self.num_mines = 40 self.num_radar = 10 self.newGameAction() def profiDiffAction(self): self.height_area = 16 self.width_area = 30 self.num_mines = 99 self.num_radar = 15 self.newGameAction() # Calling up a menu item - Special parameters def specialDiffAction(self): # Stopping the timer during the dialogue with the user self.change = False self.timerFunc(stop=True) # Calling the window for changing the parameters and passing to its data class dialog = Size(self.height_area, self.width_area, self.num_mines, self) dialog.exec_() # If the user changed the game settings if self.change: self.newGameAction() else: self.timerFunc(pause=True)
class GeneralsTab(QWidget): def __init__(self, bus, bms_com): super().__init__() self.com1 = bms_com self.bus = bus '''self.warning_label = QLabel() warning_layout = QHBoxLayout() warning_layout.addStretch() warning_layout.addWidget(self.warning_label) warning_layout.addStretch()''' #set state of charge layout self.stateofcharge = QLabel('State of Charge:') self.percentage = QLabel('%') self.line = QLineEdit() #self.fillBlanks('soc', self.line) self.line.setFixedWidth(40) self.line.setReadOnly(True) self.logo = QLabel('') self.i = QPixmap('C:/Users/iheb/BMS_UI/icons/State of charge.ico') self.logo.setPixmap(self.i.scaled(30, 30)) h_box0 = QHBoxLayout() h_box0.addSpacing(30) h_box0.addWidget(self.logo) h_box0.addWidget(self.stateofcharge) h_box0.addWidget(self.line) h_box0.addWidget(self.percentage) h_box0.addStretch() # set GeneralVolatge Layout self.voltage = QLabel("Battery Voltage") self.line2 = QLineEdit() self.line2.setFixedWidth(50) self.line2.setReadOnly(True) self.v = QLabel('V') self.logo1 = QLabel('') self.i1 = QPixmap('C:/Users/iheb/BMS_UI/icons/voltage.ico') self.logo1.setPixmap(self.i1.scaled(30, 30)) h_box2 = QHBoxLayout() h_box2.addSpacing(30) h_box2.addWidget(self.logo1) h_box2.addWidget(self.voltage) h_box2.addWidget(self.line2) h_box2.addWidget(self.v) h_box2.addStretch() # set SC Layout self.sc = QLabel("Shutdown Circuit") self.line3 = QLineEdit() self.line3.setFixedWidth(50) self.line3.setReadOnly(True) self.logo2 = QLabel('') self.i2 = QPixmap('C:/Users/iheb/BMS_UI/icons/sc.png') self.logo2.setPixmap(self.i2.scaled(30, 30)) h_box3 = QHBoxLayout() h_box3.addSpacing(30) h_box3.addWidget(self.logo2) h_box3.addWidget(self.sc) h_box3.addWidget(self.line3) h_box3.addStretch() #set Current (strom) layout self.current = QLabel("Battery Current (Strom)") self.line4 = QLineEdit() self.line4.setFixedWidth(50) self.line4.setReadOnly(True) self.c = QLabel('mA') self.logo3 = QLabel('') self.i3 = QPixmap('C:/Users/iheb/BMS_UI/icons/Strom.ico') self.logo3.setPixmap(self.i3.scaled(30, 30)) h_box4 = QHBoxLayout() h_box4.addSpacing(30) h_box4.addWidget(self.logo3) h_box4.addWidget(self.current) h_box4.addWidget(self.line4) h_box4.addWidget(self.c) h_box4.addStretch() # first vertical layout that contains 5 horizental ones v_box1 = QVBoxLayout() v_box1.addSpacing(30) v_box1.addLayout(h_box0) v_box1.addStretch() v_box1.addLayout(h_box4) v_box1.addStretch() v_box1.addLayout(h_box2) v_box1.addStretch() v_box1.addLayout(h_box3) # max voltage layout self.vm = QLabel('Voltage Max:') self.line5 = QLineEdit() self.line5.setFixedWidth(50) self.line5.setReadOnly(True) self.logo8 = QLabel('') self.i8 = QPixmap('C:/Users/iheb/BMS_UI/icons/maxVoltage.png') self.logo8.setPixmap(self.i8.scaled(30, 30)) self.v1 = QLabel('V') h_box5 = QHBoxLayout() h_box5.addSpacing(30) h_box5.addWidget(self.logo8) h_box5.addWidget(self.vm) h_box5.addWidget(self.line5) h_box5.addWidget(self.v1) h_box5.addStretch() # min Voltage Layout self.prStartTime = QLabel('Voltage Min:') self.line6 = QLineEdit() self.line6.setFixedWidth(50) self.line6.setReadOnly(True) self.logo4 = QLabel('') self.i4 = QPixmap('C:/Users/iheb/BMS_UI/icons/minVoltage.png') self.logo4.setPixmap(self.i4.scaled(30, 30)) self.s = QLabel('mV') h_box6 = QHBoxLayout() h_box6.addSpacing(30) h_box6.addWidget(self.logo4) h_box6.addWidget(self.prStartTime) h_box6.addWidget(self.line6) h_box6.addWidget(self.s) h_box6.addStretch() # max temperature Layout self.failTime = QLabel('Temperature Max:') self.line7 = QLineEdit() self.line7.setFixedWidth(50) self.line7.setReadOnly(True) self.logo5 = QLabel('') self.i5 = QPixmap('C:/Users/iheb/BMS_UI/icons/maxTemperature.png') self.logo5.setPixmap(self.i5.scaled(30, 30)) self.s1 = QLabel('C°') h_box7 = QHBoxLayout() h_box7.addSpacing(30) h_box7.addWidget(self.logo5) h_box7.addWidget(self.failTime) h_box7.addWidget(self.line7) h_box7.addWidget(self.s1) h_box7.addStretch() # min Temperature Layout self.upTime = QLabel('Temperature Min:') self.line8 = QLineEdit() self.line8.setFixedWidth(50) self.line8.setReadOnly(True) self.logo6 = QLabel('') self.i6 = QPixmap('C:/Users/iheb/BMS_UI/icons/minTemperature.png') self.logo6.setPixmap(self.i6.scaled(30, 30)) self.s2 = QLabel('C°') h_box8 = QHBoxLayout() h_box8.addSpacing(30) h_box8.addWidget(self.logo6) h_box8.addWidget(self.upTime) h_box8.addWidget(self.line8) h_box8.addWidget(self.s2) h_box8.addStretch() # second vertical layout that contains 5 horizental ones v_box2 = QVBoxLayout() v_box2.addSpacing(30) v_box2.addLayout(h_box5) v_box2.addStretch() v_box2.addLayout(h_box6) v_box2.addStretch() v_box2.addLayout(h_box7) v_box2.addStretch() v_box2.addLayout(h_box8) #Transmition error Layout self.txError = QLabel('Transmition Error: ') self.line10 = QLineEdit() self.line10.setFixedWidth(50) self.line10.setReadOnly(True) h_box10 = QHBoxLayout() h_box10.addSpacing(30) h_box10.addWidget(self.txError) h_box10.addWidget(self.line10) h_box10.addStretch() # set current State layout self.state = QLabel("Current State: ") self.line1 = QLineEdit() self.line1.setFixedWidth(120) self.line1.setReadOnly(True) h_box1 = QHBoxLayout() h_box1.addSpacing(30) h_box1.addWidget(self.state) h_box1.addWidget(self.line1) h_box1.addStretch() # dcLink Voltage Layout self.HV_state = QLabel('HV Button:') self.line9 = QLineEdit('off') self.line9.setFixedWidth(30) self.line9.setReadOnly(True) self.v2 = QLabel('V') h_box9 = QHBoxLayout() h_box9.addSpacing(30) h_box9.addWidget(self.HV_state) h_box9.addWidget(self.line9) #h_box9.addWidget(self.v2) h_box9.addStretch() #start balancing command self.startBalancing = QPushButton('Start Balancing') self.logo7 = QLabel('') self.i7 = QPixmap('C:/Users/iheb/BMS_UI/icons/balancing.png') self.logo7.setPixmap(self.i7.scaled(30, 30)) self.respond = QLabel(' ') #HV_Button_simuator self.HVButton = QPushButton('HV Button') self.logo9 = QLabel('') self.i9 = QPixmap('C:/Users/iheb/BMS_UI/icons/HV.png') self.logo9.setPixmap(self.i9.scaled(30, 30)) self.respond1 = QLabel() self.i_hv = QPixmap('C:/Users/iheb/BMS_UI/icons/respond.png') h_box15 = QHBoxLayout() h_box15.addSpacing(30) h_box15.addWidget(self.logo7) h_box15.addSpacing(10) h_box15.addWidget(self.startBalancing) h_box15.addStretch() h_box15.addWidget(self.respond) h_box15.addStretch() h_box16 = QHBoxLayout() h_box16.addSpacing(30) h_box16.addWidget(self.logo9) h_box16.addSpacing(10) h_box16.addWidget(self.HVButton) h_box16.addStretch() h_box16.addWidget(self.respond1) h_box16.addStretch() v_box4 = QVBoxLayout() v_box4.addLayout(h_box15) v_box4.addStretch() v_box4.addLayout(h_box16) v_box4.addStretch() # AirLsAux Layout '''self.airls = QLabel('AirLSAux: ') self.line11 = QLineEdit() self.line11.setFixedWidth(30) self.line11.setReadOnly(True) h_box11 = QHBoxLayout() h_box11.addSpacing(30) h_box11.addWidget(self.airls) h_box11.addWidget(self.line11) h_box11.addStretch() # AirHsAux Layout self.airhs = QLabel('AirHSAux: ') self.line12 = QLineEdit() self.line12.setFixedWidth(30) self.line12.setReadOnly(True) h_box12 = QHBoxLayout() h_box12.addSpacing(30) h_box12.addWidget(self.airhs) h_box12.addWidget(self.line12) h_box12.addStretch() # HV Button Layout self.hvButton = QLabel('HV Button: ') self.line13 = QLineEdit() self.line13.setFixedWidth(30) self.line13.setReadOnly(True) h_box13 = QHBoxLayout() h_box13.addSpacing(30) h_box13.addWidget(self.hvButton) h_box13.addWidget(self.line13) h_box13.addStretch() # Start Load Layout self.startLoad = QLabel('StartLoad: ') self.line14 = QLineEdit() self.line14.setFixedWidth(30) self.line14.setReadOnly(True) h_box14 = QHBoxLayout() h_box14.addSpacing(30) h_box14.addWidget(self.startLoad) h_box14.addWidget(self.line14) h_box14.addStretch()''' #third vertical layout that contains 5 horizental ones v_box3 = QVBoxLayout() v_box3.addSpacing(30) v_box3.addLayout(h_box10) v_box3.addStretch() v_box3.addLayout(h_box1) v_box3.addStretch() v_box3.addLayout(h_box9) v_box3.addStretch() v_box3.addLayout(v_box4) #horizental layout containing the fan controlling slider self.comment = QLabel('Enable') self.enable = QCheckBox() self.fan = QLabel('Fan Controller: ') self.lcd = QLCDNumber(self) self.sld = QSlider(Qt.Horizontal, self) self.sld.setMinimum(0) self.sld.setMaximum(100) self.sld.setTickInterval(1) palette = self.lcd.palette() palette.setColor(palette.Light, QColor(255, 0, 0)) self.lcd.setPalette(palette) self.lcd.setFixedSize(55, 30) hbox = QHBoxLayout() hbox.addStretch() hbox.addWidget(self.comment) hbox.addWidget(self.enable) hbox.addWidget(self.fan) hbox.addWidget(self.sld) hbox.addSpacing(30) hbox.addWidget(self.lcd) hbox.addStretch() # set general layout v_box0 = QVBoxLayout() h_box = QHBoxLayout() h_box.addLayout(v_box1) h_box.addStretch() h_box.addLayout(v_box2) h_box.addStretch() h_box.addLayout(v_box3) h_box.addSpacing(30) #v_box0.addLayout(warning_layout) v_box0.addLayout(h_box) v_box0.addSpacing(30) v_box = QVBoxLayout() v_box.addLayout(v_box0) v_box.addLayout(hbox) self.setLayout(v_box) self.t = QTimer() #timer for the Balancing response self.t1 = QTimer() #timer for the HV Button response self.ie = QPixmap('C:/Users/iheb/BMS_UI/icons/error.png') self.i = QPixmap('C:/Users/iheb/BMS_UI/icons/respond.png') def fillBlanks( self ): #methode that times the filling of the labels from the general tab self.timer1 = QTimer() self.timer1.timeout.connect(lambda: self.setData()) self.timer1.start(2000) def setData(self): #methode that enables the data to be set """self.d = self.data threading.Thread(target= self.d.fillData(140, 'soc')).start() threading.Thread(target=self.d.fillData(140, 'cs')).start() threading.Thread(target=self.d.fillData(140, 'bc')).start() threading.Thread(target=self.d.fillData(140, 'bv')).start() threading.Thread(target=self.d.fillData(140, 'sc')).start() threading.Thread(target=self.d.fillData(140, 'hvb')).start() threading.Thread(target=self.d.fillData(140, 'te')).start() threading.Thread(target=self.d.fillData(140, 'mxV')).start() threading.Thread(target=self.d.fillData(140, 'mnV')).start() threading.Thread(target=self.d.fillData(140, 'mxT')).start() threading.Thread(target=self.d.fillData(140, 'mnT')).start()""" self.line.setText(str(BMS_Data.getdata(cell=1, type='soc'))) self.line1.setText(str(BMS_Data.getdata(cell=1, type='cs'))) #print(str(BMS_Data.getdata(cell=1, type='cs'))) self.line2.setText(str(BMS_Data.getdata(cell=1, type='bv'))) #print(str(BMS_Data.getdata(cell=1, type='bv'))) self.line3.setText(str(BMS_Data.getdata(cell=1, type='sc'))) #print(str(BMS_Data.getdata(cell=1, type='sc'))) self.line4.setText(str(BMS_Data.getdata(cell=1, type='bc'))) #print(str(BMS_Data.getdata(cell=1, type='bc'))) self.line5.setText(str(BMS_Data.getdata(cell=1, type='mxV'))) #print(str(BMS_Data.getdata(cell=1, type='mxV'))) self.line6.setText(str(BMS_Data.getdata(cell=1, type='mnV'))) #print(str(BMS_Data.getdata(cell=1, type='mnV'))) self.line7.setText(str(BMS_Data.getdata(cell=1, type='mxT'))) #print(str(BMS_Data.getdata(cell=1, type='mxT'))) self.line8.setText(str(BMS_Data.getdata(cell=1, type='mnT'))) #print(str(BMS_Data.getdata(cell=1, type='mnT'))) self.line9.setText(str(BMS_Data.getdata(cell=1, type='hvb'))) #print(str(BMS_Data.getdata(cell=1, type='hvb'))) self.line10.setText(str(BMS_Data.getdata(cell=1, type='te'))) #print(str(BMS_Data.getdata(cell=1, type='te'))) #self.line11.setText(str(self.d.getdata(cell=1, type='airLsAux'))) #self.line12.setText(str(self.d.getdata(cell=1, type='airHsAux'))) #self.line13.setText(str(self.d.getdata(cell=1, type='hvb'))) #self.line14.setText(str(self.d.getdata(cell=1, type='sl'))) def start_Balancing(self): self.respond.setMinimumSize(30, 30) if BMS_ControlParameter.getConnectionState(): try: if self.sender().text() == 'Start Balancing': self.startBalancing.setText('Stop Balancing') self.com1.balancing(self.bus) print('balancing on') self.respond.setPixmap(self.i.scaled(30, 30)) self.t.timeout.connect(lambda: threading.Thread( target=self.response(self.t, self.respond)).start()) self.t.start(2000) else: self.startBalancing.setText('Start Balancing') self.com1.stop_balancing(self.bus) print('balancing off') self.respond.setPixmap(self.i.scaled(30, 30)) self.t.timeout.connect(lambda: threading.Thread( target=self.response(self.t, self.respond)).start()) self.t.start(2000) except Exception as e: self.respond.setPixmap(self.ie.scaled(30, 30)) logging.error(traceback.format_exc()) else: print("you need to be connected") def response(self, timer, label): label.clear() timer.stop() def HV_clicked(self): self.respond1.setMinimumSize(30, 30) if BMS_ControlParameter.getConnectionState(): try: BMS_Data.setHv(1) self.com1.HV_simulate(self.bus) self.respond1.setPixmap(self.i_hv.scaled(30, 30)) #self.t1.timeout.connect(lambda: threading.Thread(target=self.response(self.t1,self.respond1)).start()) #self.t1.start(2000) except Exception as e: self.respond1.setPixmap(self.ie.scaled(30, 30)) logging.error(traceback.format_exc()) else: print("you need to be connected") """def no_pcan(self): self.warning_label.setText('NO PCAN ADAPTER IS DETECTED, PLEASE PLUG ADAPTER AND RESTART THE PROGRAM')""" def controlFan(self, x): if self.enable.isChecked( ): #the check box needs to be checked in order to execute any command if BMS_ControlParameter.getConnectionState( ): #there needs to be connection in order to execute any command try: print(x) if (x >= 0) and (x <= 100): self.com1.sendFanControl(self.bus, x) except Exception as e: #self.enable.setChecked(False) logging.error(traceback.format_exc()) else: print("you need to be connected") def sendUserFlag(self): sender = self.sender() if BMS_ControlParameter.getConnectionState() and sender.isChecked(): self.com1.setUserFlag(self.bus) print('set') elif BMS_ControlParameter.getConnectionState() and not ( sender.isChecked()): self.com1.resetUserFlag(self.bus) print('reset') else: print('not Connected') ####################################################################################################################