コード例 #1
0
ファイル: main.py プロジェクト: globalpolicy/pyWall
    def showWindow(self):
        self.setGeometry(300, 300, 300, 63)
        self.setFixedSize(self.size())
        self.setWindowIcon(QIcon("icon.png"))
        self.setWindowTitle("pyWall UI")

        global btn
        btn = QPushButton("Change", self)
        btn.resize(75, 23)
        btn.move(0, self.height() - btn.height())
        btn.setToolTip("Change the wallpaper right now.")
        btn.clicked.connect(newWallpaperInNewThread)
        global txtinterval
        txtinterval = QTextEdit("100", self)
        txtinterval.setToolTip("Time interval in seconds between wallpaper changes.")
        txtinterval.resize(70, 23)
        txtinterval.move(0, btn.y() - txtinterval.height())
        global chkbox
        chkbox = QCheckBox("Timer", self)
        chkbox.setToolTip("Use timer for auto wallpaper change.")
        chkbox.resize(49, 17)
        chkbox.move(0, txtinterval.y() - chkbox.height())
        chkbox.stateChanged.connect(checkBoxStateChanged)
        global label
        label = QLabel("", self)
        label.setFont(QFont("Times", 8, QFont.Bold))
        label.move(btn.width() + 5, 0)
        label.resize(self.width()-btn.width(),self.height())
        label.setWordWrap(True)
        self.show()
コード例 #2
0
class WebFilesTransmitterBox(QGroupBox):
    showm_signal = pyqtSignal(str)

    def __init__(self, WebFilesTransmitter: WebFilesTransmitter, text="", parent=None):
        super(WebFilesTransmitterBox, self).__init__(text, parent)
        self.WebFilesTransmitter = WebFilesTransmitter
        self.transmitter_web_start_btn = QPushButton("开始共享", self)
        self.transmitter_web_start_btn.setGeometry(5, 22, 80, 28)
        self.transmitter_web_start_btn.clicked.connect(self.changeshare)
        # self.WebFilesTransmitter.start_btn_ss_signal.connect(self.transmitter_web_start_btn.setStyleSheet)
        self.transmitter_reset_web_port_btn = QPushButton("重置端口", self)
        self.transmitter_reset_web_port_btn.setGeometry(self.transmitter_web_start_btn.x(),
                                                        self.transmitter_web_start_btn.y() + self.transmitter_web_start_btn.height() + 10,
                                                        self.transmitter_web_start_btn.width(),
                                                        self.transmitter_web_start_btn.height())
        self.transmitter_reset_web_port_btn.clicked.connect(self.resetport)
        self.transmitter_reset_web_port_btn.setToolTip("重置端口并重启服务,此前的链接将不可以!")
        self.transmitter_web_allowupload = QCheckBox("允许上传", self)
        self.transmitter_web_allowupload.setToolTip("允许网页端上传文件,文件将保存于共享的文件夹内")
        self.transmitter_web_allowupload.setStatusTip("允许网页端上传文件,文件将保存于共享的文件夹内")
        self.transmitter_web_allowupload.setChecked(
            QSettings('Fandes', 'jamtools').value('transmitter/allowupload', True, type=bool))
        self.transmitter_web_allowupload.move(self.transmitter_reset_web_port_btn.x() + 2,
                                              self.transmitter_reset_web_port_btn.y() + self.transmitter_reset_web_port_btn.height() + 15)

        def allowuploadchange(a):
            try:
                self.WebFilesTransmitter.http_handler.canupload = True if a else False
            except:
                pass
            self.WebFilesTransmitter.canupload = True if a else False
            QSettings('Fandes', 'jamtools').setValue('transmitter/allowupload',
                                                     self.transmitter_web_allowupload.isChecked())
            if self.WebFilesTransmitter.sharing:
                self.showm_signal.emit("已{}网页端文件上传".format("允许" if a else "禁止"))

        self.transmitter_web_allowupload.stateChanged.connect(allowuploadchange)

        self.transmitter_web_need_login = QCheckBox("需要密码", self)
        self.transmitter_web_need_login.setToolTip("需要先登录")
        self.transmitter_web_need_login.setStatusTip("需要先用密码登录")
        self.transmitter_web_need_login.move(self.transmitter_web_allowupload.x(),
                                             self.transmitter_web_allowupload.y() + self.transmitter_web_allowupload.height() + 5)

        def need_loginchange(a):
            try:
                self.WebFilesTransmitter.http_handler.need_login = True if a else False
            except:
                pass
            self.WebFilesTransmitter.need_login = True if a else False
            self.transmitter_web_need_login.setChecked(a)
            self.transmitter_web_need_login_label.setVisible(bool(a))
            QSettings('Fandes', 'jamtools').setValue('transmitter/need_login',
                                                     self.transmitter_web_need_login.isChecked())

        self.transmitter_web_need_login.stateChanged.connect(need_loginchange)
        self.transmitter_web_need_login_label = QLineEdit(self)
        self.transmitter_web_need_login_label.setGeometry(self.transmitter_web_need_login.x(),
                                                          self.transmitter_web_need_login.y() + self.transmitter_web_need_login.height() - 10,
                                                          self.transmitter_web_need_login.width() - 10, 25)
        self.transmitter_web_need_login_label.setPlaceholderText("1234")
        self.transmitter_web_need_login_label.textChanged.connect(
            lambda x: QSettings('Fandes', 'jamtools').setValue('transmitter/login_password', x if len(x) else "1234"))
        self.transmitter_web_need_login_label.setText(
            QSettings('Fandes', 'jamtools').value('transmitter/login_password',
                                                  "1234"))
        need_loginchange(QSettings('Fandes', 'jamtools').value('transmitter/need_login', True, type=bool))
        self.transmitter_web_info = WebFilesTransmitter_infolabel(self)
        self.transmitter_web_info.showm_signal.connect(self.showm_signal.emit)
        self.transmitter_web_info.setGeometry(
            self.transmitter_web_start_btn.x() + self.transmitter_web_start_btn.width() + 15,
            self.transmitter_web_start_btn.y(),
            500, 200)
        print(self.transmitter_web_info.isVisible(), self.transmitter_web_info.size(), 500, "vis")

        def choicefiles():
            files, l = QFileDialog.getOpenFileNames(self, "选择要共享的文件", "", "all files(*.*);;")
            print(files)
            if len(files):
                self.WebFilesTransmitter.show_some_files(files, self.transmitter_web_allowupload.isChecked(),
                                                         self.transmitter_web_need_login.isChecked())
                self.transmitter_web_info.sharepath = os.path.split(files[0])[0] + "/{}个文件".format(len(files))

                QSettings('Fandes', 'jamtools').setValue('transmitter/sharepath', os.path.split(files[0])[0])

        def choicedir():
            dir = QFileDialog.getExistingDirectory(self, "选择要共享的文件夹",
                                                   QSettings('Fandes', 'jamtools').value('transmitter/sharepath', "",
                                                                                         str))
            print(dir)
            if len(dir):
                self.WebFilesTransmitter.show_a_dir(dir, self.transmitter_web_allowupload.isChecked(),
                                                    self.transmitter_web_need_login.isChecked())
                self.transmitter_web_info.sharepath = dir
                self.transmitter_web_info.update()
                QSettings('Fandes', 'jamtools').setValue('transmitter/sharepath', dir)

        self.transmitter_web_choice_files = QPushButton("选择文件", self)
        self.transmitter_web_choice_files.clicked.connect(choicefiles)
        self.transmitter_web_choice_files.setToolTip("选择一个文件夹内的多个文件共享")
        self.transmitter_web_choice_files.setStatusTip("选择一个文件夹内的多个文件共享")
        self.transmitter_web_choice_dir = QPushButton("选择文件夹", self)
        self.transmitter_web_choice_dir.clicked.connect(choicedir)
        self.transmitter_web_choice_dir.setToolTip("选择一个文件夹,共享整个文件夹包括其子文件夹")
        self.transmitter_web_choice_dir.setStatusTip("选择一个文件夹,共享整个文件夹包括其子文件夹")
        self.transmitter_web_choice_files.setGeometry(280, 20, 80, 23)
        self.transmitter_web_choice_dir.setGeometry(self.transmitter_web_choice_files.x(),
                                                    self.transmitter_web_choice_files.y() + self.transmitter_web_choice_files.height(),
                                                    self.transmitter_web_choice_files.width(),
                                                    self.transmitter_web_choice_files.height())
        self.transmitter_web_devices = QComboBox(self)
        self.transmitter_web_devices.setGeometry(190, 80, 140, 23)
        self.transmitter_web_devices.setToolTip("请选择要生成链接的网卡,设备需要连入共同网段才可访问共享文件,\n"
                                                "例如:本机已通过以太网连入校园网时,可选择以太网适配器生成链接和二维码,\n"
                                                "另一台已经连入该校园网的设备就可以通过链接或扫描二维码访问共享文件")
        self.transmitter_web_devices.setStatusTip("多网卡用户请选择要生成链接的网卡,设备需要连入共同网段才可访问共享文件")
        self.transmitter_web_devices.currentTextChanged.connect(
            lambda x: self.transmitter_web_info.set_info(self.WebFilesTransmitter.sharepath,
                                                         self.WebFilesTransmitter.devicedict[x],
                                                         self.WebFilesTransmitter.port) if x != "" else None)
        update_btn = QPushButton(QIcon(":/update.png"), "", self)
        update_btn.setToolTip("刷新设备,如改变了wifi/移动热点请刷新一下以获取正确的链接")
        update_btn.setGeometry(self.transmitter_web_devices.x() + self.transmitter_web_devices.width() + 5,
                               self.transmitter_web_devices.y(), 20, 20)
        update_btn.clicked.connect(self.updatedevice)
        d = QSettings('Fandes', 'jamtools').value('transmitter/sharepath', "")
        if d != "":
            self.WebFilesTransmitter.show_a_dir(d, self.transmitter_web_allowupload.isChecked(),
                                                self.transmitter_web_need_login.isChecked())
            self.transmitter_web_info.sharepath = d

    def changeshare(self):
        if self.transmitter_web_info.sharepath == "请先选择要共享的文件":
            self.showm_signal.emit("未选择要共享的路径/文件!")
            print("未选择要共享的路径")
            return
        if self.WebFilesTransmitter.sharing:
            print("停止共享")
            self.transmitter_web_start_btn.setStyleSheet("QPushButton{background-color:rgb(239,239,239);}")
            self.transmitter_web_start_btn.setText("开始共享")
            self.WebFilesTransmitter.stop_server()
        else:
            self.transmitter_web_start_btn.setStyleSheet("QPushButton{background-color:rgb(255,50,50);}")
            self.transmitter_web_start_btn.setText("结束共享")
            self.WebFilesTransmitter.start()
            print("开始共享")

    def resetport(self):
        sharing = self.WebFilesTransmitter.sharing
        if sharing:
            try:
                self.changeshare()
            except:
                print(sys.exc_info())
        self.WebFilesTransmitter.port = random.randint(6048, 65530)
        QSettings('Fandes', 'jamtools').setValue("webtransmitterport", self.WebFilesTransmitter.port)
        if sharing:
            self.WebFilesTransmitter.wait()
            self.changeshare()
        self.updatedevice()

    def updatedevice(self):
        # print("baseppppppppppppp", sys.path)
        self.transmitter_web_devices.clear()
        self.transmitter_web_devices.addItems(self.WebFilesTransmitter.get_alldevices().keys())
コード例 #3
0
ファイル: GUI.py プロジェクト: xiaohaokan/Pendulum
class MainWindow(QWidget):
    """Окно графического интерфейса"""
    def __init__(self):
        super().__init__()

        self.sim = PendulumLearning(
            self
        )  # Объект с моделью и обучающейся системой управления маятником

        # Элементы интерфейса
        self.canvas_width = 800  # Ширина холста
        self.canvas_height = 675  # Длина холста
        self.canvas = Plotter(self.canvas_width,
                              self.canvas_height,
                              dpi=100,
                              parent=self)  # Холст с графиками
        # Кнопки
        self.start_button = QPushButton('Start', self)
        self.stop_button = QPushButton('Stop', self)
        self.restart_button = QPushButton('Restart', self)
        self.new_nn_button = QPushButton('New neural net', self)
        self.load_nn_button = QPushButton('Load neural net', self)
        self.save_nn_button = QPushButton('Save neural net', self)
        self.save_plots_button = QPushButton('Save plots', self)
        self.clear_button = QPushButton('Clear', self)
        # Надписи
        self.eps_start_label = QLabel('Initial probability\nof random action',
                                      self)
        self.eps_discount_label = QLabel(
            'Discount of probability\non each step', self)
        self.eps_final_label = QLabel('Final probability\nof random action',
                                      self)
        self.episode_length_label = QLabel('Episode length', self)
        self.batch_size_label = QLabel('Training batch\nsize', self)
        # Поля ввода чисел
        self.eps_start_spinbox = QDoubleSpinBox(self)
        self.eps_discount_spinbox = QDoubleSpinBox(self)
        self.eps_final_spinbox = QDoubleSpinBox(self)
        self.episode_length_spinbox = QSpinBox(self)
        self.batch_size_spinbox = QSpinBox(self)
        # Кнопки выбора обучающейся модели
        self.q_learning_rb = QRadioButton("Deep Q-learning", self)
        self.q_learning2_rb = QRadioButton("Q-learning, net with one output",
                                           self)
        self.actor_critic_rb = QRadioButton("Adaptive critic", self)
        self.actor_critic_DDPG_rb = QRadioButton("Adaptive critic (DDPG)",
                                                 self)
        # Чекбоксы
        self.eps_greedy_checkbox = QCheckBox("Use random actions", self)
        self.learning_checkbox = QCheckBox("Turn training on", self)
        self.endless_episode_checkbox = QCheckBox("Endless episode", self)
        # Вывод данных
        self.output_text_field = QTextBrowser(self)

        self.initUI()

    def initUI(self):
        """Формирование интерфейса"""
        size = (1300, 715)  # Размер окна
        position = (100, 100)  # Начальная позиция окна
        canvas_position = (20, 20)  # Верхний левый угол холста
        buttons_indent = 10  # Расстояние между кнопками
        spinbox_indent = 8  # Расстояние между полями выбора чисел
        labels_indent = 5  # Расстояние между надписями
        # Параметры поля выбора начальной вероятности выбора случайного действия
        eps_start_min = 0
        eps_start_max = 1
        eps_start_step = 0.1
        eps_start_default_value = 0.5
        # Параметры поля выбора шага уменьшения вероятности случайного действия
        eps_discount_min = 0
        eps_discount_max = 1
        eps_discount_step = 0.000001
        eps_discount_default_value = 0.00002
        eps_discount_decimals = 6
        # Параметры поля выбора конечной вероятности выбора случайного действия
        eps_final_min = 0
        eps_final_max = 1
        eps_final_step = 0.01
        eps_final_default_value = 0.05
        # Параметры поля выбора длины эпизода
        episode_length_min = 1
        episode_length_max = 2000
        episode_length_step = 100
        episode_length_default_value = 200
        # Параметры поля выбора размера пачки при обучении
        batch_size_min = 1
        batch_size_max = 300
        batch_size_step = 10
        batch_size_default_value = 50
        # Размер поля вывода данных
        text_field_size = (460, 170)

        buttons_left = canvas_position[
            0] + buttons_indent + self.canvas_width  # Координата левого края блока элементов управления
        buttons_up = canvas_position[
            1]  # Координата верхнего края блока элементов управления

        # Изменяем позицию и перемещаем окно
        self.resize(*size)
        self.move(*position)

        self.canvas.move(*canvas_position)

        # Кнопки старт, стоп, перезапуск
        button_up = buttons_up  # Верхняя позиция текущей кнопки
        self.start_button.resize(self.start_button.sizeHint())
        self.start_button.move(buttons_left, button_up)
        self.start_button.clicked.connect(self.start)

        buttons_distance = self.start_button.height(
        ) + buttons_indent  # Расстояние между верхними позициями кнопок
        spinbox_distance = self.eps_start_spinbox.height() + spinbox_indent
        button_up += buttons_distance

        self.stop_button.resize(self.start_button.sizeHint())
        self.stop_button.move(buttons_left, button_up)
        self.stop_button.clicked.connect(self.stop)
        button_up += buttons_distance

        self.restart_button.resize(self.start_button.sizeHint())
        self.restart_button.move(buttons_left, button_up)
        self.restart_button.clicked.connect(self.restart)

        # Элементы для настройки случайных действий
        # Координата левого края блока элементов для генерации случайной среды
        controls_left = buttons_left + self.start_button.width(
        ) + buttons_indent

        element_up = buttons_up  # Верхняя позиция текущего элемента управления
        self.eps_start_label.resize(self.eps_start_label.sizeHint())
        self.eps_start_label.move(controls_left, element_up)
        element_left = controls_left + self.eps_start_label.width(
        ) + buttons_indent
        self.eps_start_spinbox.move(element_left, element_up)
        self.eps_start_spinbox.setMinimum(eps_start_min)
        self.eps_start_spinbox.setMaximum(eps_start_max)
        self.eps_start_spinbox.setSingleStep(eps_start_step)
        self.eps_start_spinbox.setValue(eps_start_default_value)
        self.eps_start_spinbox.valueChanged.connect(self.change_start_eps)
        self.change_start_eps()
        element_up += spinbox_distance

        self.eps_final_label.resize(self.eps_final_label.sizeHint())
        self.eps_final_label.move(controls_left, element_up)
        element_left = controls_left + self.eps_final_label.width(
        ) + buttons_indent
        self.eps_final_spinbox.move(element_left, element_up)
        self.eps_final_spinbox.setMinimum(eps_final_min)
        self.eps_final_spinbox.setMaximum(eps_final_max)
        self.eps_final_spinbox.setSingleStep(eps_final_step)
        self.eps_final_spinbox.setValue(eps_final_default_value)
        self.eps_final_spinbox.valueChanged.connect(self.change_final_eps)
        self.change_final_eps()
        element_up += spinbox_distance

        self.eps_discount_label.resize(self.eps_discount_label.sizeHint())
        self.eps_discount_label.move(controls_left, element_up)
        element_left = controls_left + self.eps_discount_label.width(
        ) + buttons_indent
        self.eps_discount_spinbox.setDecimals(eps_discount_decimals)
        self.eps_discount_spinbox.resize(self.eps_discount_spinbox.sizeHint())
        self.eps_discount_spinbox.move(element_left, element_up)
        self.eps_discount_spinbox.setMinimum(eps_discount_min)
        self.eps_discount_spinbox.setMaximum(eps_discount_max)
        self.eps_discount_spinbox.setSingleStep(eps_discount_step)
        self.eps_discount_spinbox.setValue(eps_discount_default_value)
        self.eps_discount_spinbox.valueChanged.connect(
            self.change_eps_discount)
        self.change_eps_discount()
        element_up += spinbox_distance

        self.eps_greedy_checkbox.resize(self.eps_greedy_checkbox.sizeHint())
        self.eps_greedy_checkbox.move(controls_left, element_up)
        self.eps_greedy_checkbox.setChecked(True)
        self.eps_greedy_checkbox.stateChanged.connect(self.toggle_eps_greedy)
        self.toggle_eps_greedy()

        labels_distance = self.eps_greedy_checkbox.height() + labels_indent

        element_up += labels_distance

        button_up = max([element_up, button_up])
        self.q_learning_rb.move(buttons_left, button_up)
        self.q_learning_rb.setChecked(True)
        self.q_learning_rb.toggled.connect(self.select_learning_model)
        button_up += labels_distance
        self.q_learning2_rb.move(buttons_left, button_up)
        self.q_learning2_rb.toggled.connect(self.select_learning_model)
        button_up += labels_distance
        self.actor_critic_rb.move(buttons_left, button_up)
        self.actor_critic_rb.toggled.connect(self.select_learning_model)
        button_up += labels_distance
        self.actor_critic_DDPG_rb.move(buttons_left, button_up)
        self.actor_critic_DDPG_rb.toggled.connect(self.select_learning_model)
        self.select_learning_model()
        button_up += labels_distance

        self.learning_checkbox.move(buttons_left, button_up)
        self.learning_checkbox.setChecked(True)
        self.learning_checkbox.stateChanged.connect(self.toggle_learning)
        self.toggle_learning()

        button_up += labels_distance
        self.batch_size_label.resize(self.batch_size_label.sizeHint())
        self.batch_size_label.move(buttons_left, button_up)
        element_left = buttons_left + self.batch_size_label.width(
        ) + buttons_indent
        self.batch_size_spinbox.resize(self.batch_size_spinbox.sizeHint())
        self.batch_size_spinbox.move(element_left, button_up)
        self.batch_size_spinbox.setMinimum(batch_size_min)
        self.batch_size_spinbox.setMaximum(batch_size_max)
        self.batch_size_spinbox.setSingleStep(batch_size_step)
        self.batch_size_spinbox.setValue(batch_size_default_value)
        self.batch_size_spinbox.valueChanged.connect(self.change_batch_size)
        self.change_batch_size()
        button_up += spinbox_distance

        element_up = button_up

        self.new_nn_button.resize(self.save_nn_button.sizeHint())
        self.new_nn_button.move(buttons_left, button_up)
        self.new_nn_button.clicked.connect(self.new_nn)
        button_up += buttons_distance

        self.load_nn_button.resize(self.save_nn_button.sizeHint())
        self.load_nn_button.move(buttons_left, button_up)
        self.load_nn_button.clicked.connect(self.load_nn)
        button_up += buttons_distance

        self.save_nn_button.resize(self.save_nn_button.sizeHint())
        self.save_nn_button.move(buttons_left, button_up)
        self.save_nn_button.clicked.connect(self.save_nn)
        button_up += buttons_distance

        elements_left = buttons_left + self.save_nn_button.width(
        ) + buttons_indent

        self.save_plots_button.resize(self.save_plots_button.sizeHint())
        self.save_plots_button.move(elements_left, element_up)
        self.save_plots_button.clicked.connect(self.save_plots)
        element_up += buttons_distance

        self.clear_button.resize(self.save_plots_button.sizeHint())
        self.clear_button.move(elements_left, element_up)
        self.clear_button.clicked.connect(self.clear)
        element_up += buttons_distance

        self.episode_length_label.resize(self.episode_length_label.sizeHint())
        self.episode_length_label.move(buttons_left, button_up)
        element_left = buttons_left + self.episode_length_label.width(
        ) + buttons_indent
        self.episode_length_spinbox.resize(
            self.episode_length_spinbox.sizeHint())
        self.episode_length_spinbox.move(element_left, button_up)
        self.episode_length_spinbox.setMinimum(episode_length_min)
        self.episode_length_spinbox.setMaximum(episode_length_max)
        self.episode_length_spinbox.setSingleStep(episode_length_step)
        self.episode_length_spinbox.setValue(episode_length_default_value)
        self.episode_length_spinbox.valueChanged.connect(
            self.change_episode_length)
        self.change_episode_length()
        button_up += spinbox_distance

        self.endless_episode_checkbox.move(buttons_left, button_up)
        self.endless_episode_checkbox.setChecked(False)
        self.endless_episode_checkbox.stateChanged.connect(
            self.toggle_endless_episode)
        self.toggle_endless_episode()
        button_up += labels_distance

        self.output_text_field.resize(*text_field_size)
        self.output_text_field.move(buttons_left, button_up)
        self.output_text_field.setReadOnly(True)
        self.setWindowTitle('An Inverted Pendulum')
        self.show()

    def closeEvent(self, event):
        """Закрытие окна"""
        self.sim.exit()
        self.deleteLater()
        self.close()

    def start(self):
        """Запуск моделирования"""
        self.sim.start()

    def stop(self):
        """Остановка моделирования"""
        self.sim.stop()

    def restart(self):
        """Поместить маятник в случайную позицию"""
        self.sim.restart()

    def change_start_eps(self):
        """Изменить начальную вероятность случайного действия"""
        self.sim.set_eps(self.eps_start_spinbox.value())

    def change_final_eps(self):
        """Изменить конечную вероятность случайного действия"""
        self.sim.set_final_eps(self.eps_final_spinbox.value())

    def change_eps_discount(self):
        """Изменить шаг уменьшения вероятности случайного действия"""
        self.sim.set_eps_discount(self.eps_discount_spinbox.value())

    def select_learning_model(self):
        """Выбрать обучающуюся модель"""
        if self.q_learning_rb.isChecked():
            lm_number = 0
        elif self.q_learning2_rb.isChecked():
            lm_number = 1
        elif self.actor_critic_rb.isChecked():
            lm_number = 2
        else:
            lm_number = 3
        self.sim.choose_learning_model(lm_number)

    def toggle_eps_greedy(self):
        """Включить или отключить совершение случайных действий"""
        self.sim.set_eps_greedy(self.eps_greedy_checkbox.isChecked())

    def toggle_learning(self):
        """Производить ли обучение модели, или просто включить управление"""
        enable = self.learning_checkbox.isChecked()
        self.sim.is_learning = enable

    def save_plots(self):
        """Сохранить графики в файл"""
        file_dialogue = QFileDialog()
        file_dialogue.setFileMode(QFileDialog.AnyFile)
        file_dialogue.setAcceptMode(QFileDialog.AcceptSave)
        name_filters = ["PNG images (*.png)", "All files (*.*)"]
        file_dialogue.setNameFilters(name_filters)
        if file_dialogue.exec():
            filename = file_dialogue.selectedFiles()[0]
            try:
                self.canvas.figure.savefig(filename)
            except PermissionError as e:
                QMessageBox.warning(self, "Error", str(e))
                self.canvas.draw()
        file_dialogue.deleteLater()

    def change_batch_size(self):
        """Изменить размер пачки при обучении нейросетей"""
        self.sim.set_batch_size(self.batch_size_spinbox.value())

    def new_nn(self):
        """Создать новую нейросеть со случайными коэффициентами"""
        self.sim.new_nn()  # Создать новую нейросеть и очистить опыт
        self.change_start_eps()  # Обновить вероятность случайного действия

    def load_nn(self):
        """Загрузить нейросеть из файла"""
        file_dialogue = QFileDialog()
        file_dialogue.setFileMode(QFileDialog.ExistingFile)
        file_dialogue.setAcceptMode(QFileDialog.AcceptOpen)
        if self.actor_critic_rb.isChecked(
        ) or self.actor_critic_DDPG_rb.isChecked():
            name_filters = ["TensorFlow session (*.meta)"]
        else:
            name_filters = [
                "Hierarchical data format (*.hdf)", "All files (*.*)"
            ]
        file_dialogue.setNameFilters(name_filters)
        if file_dialogue.exec():
            filename = file_dialogue.selectedFiles()[0]
            try:
                self.sim.load_nn(filename)
            except OSError or FileNotFoundError or FileNotFoundError as e:
                QMessageBox.warning(self, "Error", str(e))
        file_dialogue.deleteLater()

    def save_nn(self):
        """Сохранить нейросеть в файл"""
        file_dialogue = QFileDialog()
        file_dialogue.setFileMode(QFileDialog.AnyFile)
        file_dialogue.setAcceptMode(QFileDialog.AcceptSave)
        if self.actor_critic_rb.isChecked(
        ) or self.actor_critic_DDPG_rb.isChecked():
            name_filters = ["TensorFlow session (*.*)"]
        else:
            name_filters = [
                "Hierarchical data format (*.hdf)", "All files (*.*)"
            ]
        file_dialogue.setNameFilters(name_filters)
        if file_dialogue.exec():
            filename = file_dialogue.selectedFiles()[0]
            try:
                self.sim.save_nn(filename)
            except PermissionError as e:
                QMessageBox.warning(self, "Error", str(e))
        file_dialogue.deleteLater()

    def change_episode_length(self):
        """Изменить длину эпизода - количества шагов перед случайным выбором новой позиции маятника"""
        episode_length = self.episode_length_spinbox.value()
        self.sim.max_ep_steps = episode_length

    def toggle_endless_episode(self):
        """Никогда не выбирать случайную позицию для маятника"""
        enable = self.endless_episode_checkbox.isChecked()
        self.sim.endless = enable

    def clear(self):
        """Очистить графики и поле с информацией об обучении"""
        self.canvas.clear()
        self.canvas.draw()
        self.output_text_field.clear()

    def paint_scene(self, thetas, omegas, moments, times, running_reward,
                    episode):
        """Рисовать графики"""
        self.canvas.clear()
        self.canvas.theta_plot.plot(times, thetas, 'b')
        self.canvas.omega_plot.plot(times, omegas, 'g')
        self.canvas.moment_plot.plot(times, moments, 'r')
        self.canvas.draw()
        eps = self.sim.get_eps()
        self.output_text_field.append(
            "Episode %d: running reward: %d, random probability: %-10.5g" %
            (episode, running_reward, eps))