Ejemplo n.º 1
1
	def __init__(self, window:QMainWindow, system_info):
		super().__init__()
		v_box = QVBoxLayout()
		h_buttons = QHBoxLayout()

		button_style = "background-color: #006699; padding-left:20px; padding-right:20px; padding-top:5px; padding-bottom:5px;"
		copy_pastable_json = json.dumps(system_info, indent=2)
		website_link = str(base64.b64decode("aHR0cHM6Ly90YXJhbGxvLndlZWVvcGVuLml0L2J1bGsvYWRkCg=="), "utf-8")

		self.clipboard_button = QPushButton("Copy to clipboard")
		self.clipboard_button.setStyleSheet(button_style)
		self.clipboard_button.clicked.connect(lambda: QApplication.clipboard().setText(copy_pastable_json))
		self.clipboard_button.clicked.connect(lambda: self.spawn_notification("Copied to clipboard"))

		self.website_button = QPushButton("Go to T.A.R.A.L.L.O.")
		self.website_button.setStyleSheet(button_style)
		self.website_button.clicked.connect(lambda: sp.Popen(["xdg-open", website_link]))

		plain_text = QPlainTextEdit()
		plain_text.document().setPlainText(copy_pastable_json)
		plain_text.setStyleSheet("background-color:#333333; color:#bbbbbb")
		plain_text.setReadOnly(True)
		plain_text.setMinimumSize(plain_text.width(), plain_text.height())
		# prevent from resizing too much

		back_button = QPushButton("Go back")
		back_button.clicked.connect(lambda: self.restore_previous_window(window, system_info))

		h_buttons.addWidget(self.clipboard_button, alignment=Qt.AlignCenter)
		h_buttons.addWidget(self.website_button, alignment=Qt.AlignCenter)

		v_box.addLayout(h_buttons)
		v_box.addWidget(plain_text)
		v_box.addWidget(back_button, alignment=Qt.AlignCenter)
		self.setLayout(v_box)
Ejemplo n.º 2
0
    def __init__(self, window: QMainWindow, system_info):
        super().__init__()
        v_box = QVBoxLayout()
        h_buttons = QHBoxLayout()
        s_buttons = QHBoxLayout()

        button_style = "background-color: #006699; padding-left:20px; padding-right:20px; padding-top:5px; padding-bottom:5px;"
        copy_pastable_json = json.dumps(system_info, indent=2)

        self.back_button = QPushButton("Go back")
        self.back_button.setStyleSheet(
            "padding-left:20px; padding-right:20px; padding-top:5px; padding-bottom:5px;"
        )
        self.back_button.clicked.connect(
            lambda: self.restore_previous_window(window, system_info))
        h_buttons.addWidget(self.back_button, alignment=Qt.AlignLeft)

        plain_text = QPlainTextEdit()
        plain_text.document().setPlainText(copy_pastable_json)
        plain_text.setStyleSheet("background-color:#333333; color:#bbbbbb")
        plain_text.setReadOnly(True)
        plain_text.setMinimumSize(plain_text.width(), plain_text.height())
        # prevent from resizing too much

        layout_grid = QGridLayout()

        self.lbl_manual = QLabel("Manual")
        layout_grid.addWidget(self.lbl_manual, 0, 1, Qt.AlignCenter)

        self.clipboard_button = QPushButton("Copy to clipboard")
        self.clipboard_button.setStyleSheet(button_style)
        self.clipboard_button.clicked.connect(
            lambda: QApplication.clipboard().setText(copy_pastable_json))
        self.clipboard_button.clicked.connect(
            lambda: self.spawn_notification("Copied to clipboard"))
        layout_grid.addWidget(self.clipboard_button, 1, 1, Qt.AlignCenter)

        self.website_button = QPushButton("Go to T.A.R.A.L.L.O.")
        self.website_button.setStyleSheet(button_style)
        self.website_button.clicked.connect(
            lambda: _go_to_tarallo("/bulk/add"))
        layout_grid.addWidget(self.website_button, 2, 1, Qt.AlignCenter)

        self.lbl_automatic = QLabel("Automatic")
        layout_grid.addWidget(self.lbl_automatic, 0, 0, Qt.AlignCenter)

        self.tarallo_data = QPushButton("Send data to T.A.R.A.L.L.O.")
        self.tarallo_data.setStyleSheet(button_style)
        self.tarallo_data.clicked.connect(lambda: self.send_data(system_info))
        layout_grid.addWidget(self.tarallo_data, 1, 0, -1, 1, Qt.AlignCenter)

        v_box.addLayout(h_buttons)
        v_box.addWidget(plain_text)
        v_box.addLayout(layout_grid)

        self.setLayout(v_box)
Ejemplo n.º 3
0
class DefaultWidget(QWidget):
    """
    The default widget for a repeating element.
    It's a simple line edit with a label and an option required astrix.
    """
    def __init__(
        self,
        label="",
        line_name="na",
        required=False,
        placeholder_text=None,
        spellings=True,
        parent=None,
    ):
        """

        Parameters
        ----------
        label : str
            The label that appears next to the text edit
        line_name : str
            The name to use for the text edit
        required : boolean
            Whethere to display the little blue required asterix
        parent : QWidget

        """
        QWidget.__init__(self, parent=parent)
        self.layout = QHBoxLayout()
        self.qlbl = QLabel(label, self)
        self.added_line = QPlainTextEdit()
        max_line_height = self.added_line.fontMetrics().height() + 10
        self.added_line.setMaximumHeight(max_line_height)
        self.added_line.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.added_line.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.added_line.mouseMoveEvent = self.mouse_move
        self.added_line.setLineWrapMode(QPlainTextEdit.NoWrap)
        self.added_line.textChanged.connect(self.remove_returns)
        if spellings:
            self.highlighter = Highlighter(self.added_line.document())

        if not placeholder_text is None:
            self.added_line.setPlaceholderText(placeholder_text)
        self.added_line.setObjectName(line_name)
        self.layout.addWidget(self.qlbl)
        self.layout.addWidget(self.added_line)

        if required:
            self.required_label = QLabel(self)
            font = QFont()
            font.setFamily("Arial")
            font.setPointSize(9)
            font.setBold(False)
            font.setItalic(False)
            font.setWeight(50)
            self.required_label.setFont(font)
            self.required_label.setScaledContents(True)
            self.required_label.setAlignment(QtCore.Qt.AlignHCenter
                                             | QtCore.Qt.AlignVCenter)
            self.required_label.setIndent(0)

            self.required_label.setText(
                QtCore.QCoreApplication.translate(
                    "",
                    '<html><head/><body><p align="center">'
                    '<span style=" font-size:18pt; color:#55aaff;">*'
                    "</span></p></body></html>",
                ))
            self.layout.addWidget(self.required_label)

        self.layout.setContentsMargins(1, 1, 1, 1)
        self.layout.setSpacing(10)
        self.setLayout(self.layout)

    def mouse_move(self, e):
        """
        over ride the mouse move event to ignore mouse movement (scrolling),
        but only in the vertical dimension.  Makes this plain text edit look and
        feel like a line edit.

        Parameters
        ----------
        e : pyqt event

        Returns
        -------
        None
        """
        if e.y() < self.added_line.height() - 3 and e.x(
        ) < self.added_line.width() - 3:
            QPlainTextEdit.mouseMoveEvent(self.added_line, e)
        self.added_line.verticalScrollBar().setValue(
            self.added_line.verticalScrollBar().minimum())

    def remove_returns(self):
        """
        After changes to the line, we need to make sure that the user has not entered any line returns, since the
        single line is not intended to be a multiline string.  Any line returns "\n" will be replace with a ' '

        Returns
        -------
        None
        """
        self.added_line.textChanged.disconnect()
        old_position = self.added_line.textCursor().position()
        curtext = self.added_line.toPlainText()
        newtext = curtext.replace("\n", " ")
        self.added_line.setPlainText(newtext)
        cursor = self.added_line.textCursor()
        cursor.setPosition(old_position)
        self.added_line.setTextCursor(cursor)
        self.added_line.textChanged.connect(self.remove_returns)

    def setText(self, text):
        utils.set_text(self.added_line, text)
        cursor = self.added_line.textCursor()
        cursor.setPosition(0)
        self.added_line.setTextCursor(cursor)

    def text(self):
        return self.added_line.toPlainText()
Ejemplo n.º 4
0
class Window(QWidget):
    def __init__(self):
        super().__init__()

        self.title = "Textbox Generator"

        QFontDatabase.addApplicationFont(
            os.path.dirname(__file__) + "/space_station.ttf")

        self.textbox_position_x = 20
        self.textbox_position_y = 20
        self.textbox_position_type = 0
        self.textbox_color = 0
        self.textbox_text = ""

        self.textbox_squeak = 0
        self.textbox_position_crewmate = 0

        self.InitWindow()

    def InitWindow(self):
        self.setWindowIcon(
            QtGui.QIcon(os.path.dirname(__file__) + "/icon.png"))
        self.setWindowTitle(self.title)

        self.resize(640, 480)

        self.layout = QGridLayout()

        self.widget_textbox = TextboxWidget()
        self.widget_text_input_label = QLabel('Text:')
        self.widget_text_input = QPlainTextEdit()

        self.widget_save_image = QPushButton("Save image")
        self.widget_copy_image = QPushButton("Copy image to clipboard")

        self.widget_color_label = QLabel('Color:')
        self.widget_color = QComboBox()
        self.widget_color.addItems(color_names)

        self.widget_position_label = QLabel('Position:')
        self.widget_position = QComboBox()
        self.widget_position.addItems([
            "Centered", "Horizontally centered", "Vertically centered",
            "Above...", "Below...", "Absolute"
        ])
        self.widget_position_above = QComboBox()
        self.widget_position_above.addItems(crewmate_positions)
        self.widget_position_edit = QPushButton("Place textbox")
        self.widget_position_x = QSpinBox()
        self.widget_position_y = QSpinBox()

        self.widget_squeak_label = QLabel('Squeak:')
        self.widget_squeak = QComboBox()
        self.widget_squeak.addItems(squeaks)

        self.widget_text_output_label = QLabel('Generated script:')
        self.widget_text_output = QPlainTextEdit()

        self.widget_text_input.textChanged.connect(self.text_updated)
        self.widget_text_input.resize(165, self.widget_text_input.height())

        self.widget_color.currentIndexChanged.connect(self.change_color)

        self.widget_squeak.currentIndexChanged.connect(self.change_squeak)

        self.layout.addWidget(self.widget_textbox, 0, 0, 1, 0)
        self.layout.addWidget(self.widget_save_image, 1, 0)
        self.layout.addWidget(self.widget_copy_image, 1, 1)
        self.layout.addWidget(self.widget_text_input_label, 2, 0)
        self.layout.addWidget(self.widget_text_input, 3, 0, 1, 6)
        self.layout.addWidget(self.widget_color_label, 4, 0)
        self.layout.addWidget(self.widget_color, 4, 1, 1, 5)
        self.layout.addWidget(self.widget_position_label, 5, 0)
        self.layout.addWidget(self.widget_position, 5, 1)
        self.layout.addWidget(self.widget_position_above, 5, 2)
        self.layout.addWidget(self.widget_position_edit, 5, 3)
        self.layout.addWidget(self.widget_position_x, 5, 4)
        self.layout.addWidget(self.widget_position_y, 5, 5)
        self.layout.addWidget(self.widget_squeak_label, 6, 0)
        self.layout.addWidget(self.widget_squeak, 6, 1, 1, 5)
        self.layout.addWidget(self.widget_text_output_label, 7, 0)
        self.layout.addWidget(self.widget_text_output, 7, 1, 1, 5)

        self.widget_position_above.setEnabled(False)
        self.widget_position_edit.setEnabled(False)
        self.widget_save_image.clicked.connect(self.save_image)
        self.widget_copy_image.clicked.connect(self.copy_image)
        self.widget_position_edit.clicked.connect(self.edit_position)
        self.widget_position.currentIndexChanged.connect(self.change_buttons)
        self.widget_position_above.currentIndexChanged.connect(
            self.change_position_above)
        self.widget_position_x.valueChanged.connect(self.change_position_x)
        self.widget_position_y.valueChanged.connect(self.change_position_y)
        self.widget_position_x.setRange(0, 320)
        self.widget_position_y.setRange(0, 240)
        self.widget_position_x.setValue(10)
        self.widget_position_y.setValue(10)
        self.widget_position_x.setEnabled(False)
        self.widget_position_y.setEnabled(False)

        self.update_script()

        self.layout.setColumnStretch(1, 1)
        self.setLayout(self.layout)
        self.show()

    def text_updated(self):
        self.textbox_text = self.widget_text_input.toPlainText()
        self.widget_textbox.text_updated(self.textbox_text)
        self.update_script()

    def change_color(self, ind):
        self.widget_textbox.change_color(ind)
        self.textbox_color = ind
        self.update_script()

    def change_squeak(self, ind):
        self.textbox_squeak = ind
        self.update_script()

    def edit_position(self):
        self.window = PositionWindow(self)
        self.window.setWindowModality(Qt.ApplicationModal)

        def update():
            self.textbox_position_x = self.window.textbox_x
            self.textbox_position_y = self.window.textbox_y
            self.widget_position_x.setValue(
                math.floor(self.textbox_position_x / 2))
            self.widget_position_y.setValue(
                math.floor(self.textbox_position_y / 2))
            self.update_script()

        self.window.show()
        self.window.destroyed.connect(update)

    def save_image(self):

        fname = QFileDialog.getSaveFileName(
            self, 'Save image', './',
            "PNG (*.png);;JPEG (*.jpg; *.jpeg);;BMP (*.bmp);;TIFF (*.tiff; *.tif);;GIF (*.gif);;WEBP (*.webp)"
        )
        if not fname[0]:
            return

        image = QImage(640, 480, QImage.Format_RGB32)
        painter = QtGui.QPainter(image)
        text_width, text_height = PaintTextbox(painter, 0, 0,
                                               self.textbox_text,
                                               colors[self.textbox_color])
        painter.end()
        width = text_width + 32
        height = text_height + 32

        image2 = image.copy(0, 0, width, height)
        image2.save(fname[0])

        pass

    def copy_image(self):
        image = QImage(640, 480, QImage.Format_RGB32)
        painter = QtGui.QPainter(image)
        text_width, text_height = PaintTextbox(painter, 0, 0,
                                               self.textbox_text,
                                               colors[self.textbox_color])
        painter.end()
        width = text_width + 32
        height = text_height + 32

        image2 = image.copy(0, 0, width, height)
        QApplication.clipboard().setImage(image2)

    def change_buttons(self, index):
        self.textbox_position_type = index
        self.widget_position_above.setEnabled(False)
        self.widget_position_edit.setEnabled(False)
        self.widget_position_x.setEnabled(False)
        self.widget_position_y.setEnabled(False)
        if index in [1, 2, 5]:
            self.widget_position_edit.setEnabled(True)
        if index in [3, 4]:
            self.widget_position_above.setEnabled(True)
        if index in [1, 5]:
            self.widget_position_y.setEnabled(True)
        if index in [2, 5]:
            self.widget_position_x.setEnabled(True)
        self.update_script()

    def change_position_above(self, index):
        self.textbox_position_crewmate = index
        self.update_script()

    def change_position_x(self, index):
        self.textbox_position_x = math.floor(index * 2)
        self.update_script()

    def change_position_y(self, index):
        self.textbox_position_y = math.floor(index * 2)
        self.update_script()

    def update_script(self):

        lines = []
        for line in self.textbox_text.split("\n"):
            lines.append("\n".join(
                textwrap.wrap(line, width=36, drop_whitespace=False)))
        text = "\n".join(lines)

        script = ""
        if self.textbox_squeak != 0:
            script += "squeak(" + squeaks[self.textbox_squeak].lower() + ")\n"
        script += "text("
        script += GetRealColorName(self.textbox_color).lower() + ","
        script += str(math.floor(self.textbox_position_x / 2)) + "," + str(
            math.floor(self.textbox_position_y / 2)) + "," + str(
                len(text.split("\n"))) + ")\n"
        script += text + "\n"
        if self.textbox_color > 6:
            script += "createcrewman(-20,0,gray,0,faceleft)\n"
        if self.textbox_position_type != 5:
            script += "position("
            translation = ["center", "centerx", "centery", "above", "below"]
            if self.textbox_position_type in range(0, 3):
                script += translation[self.textbox_position_type]
            else:
                script += crewmate_positions[
                    self.textbox_position_crewmate].lower()
                script += ","
                script += translation[self.textbox_position_type]
            script += ")\n"
        script += "speak_active\n"
        script += "endtext"

        self.widget_text_output.setPlainText(script)
class Ui_userDefine(QWidget):
    def __init__(self):
        super().__init__()
        self.model = None
        self.playing_index = -1
        self.problem_solving = False

    def initUI(self):
        self.resize(1200, 700)

        self.timer = QBasicTimer()
        widget1 = QWidget(parent=self)
        widget1.setGeometry(QRect(30, 50, 800, 500))
        table_area = QGroupBox(parent=widget1)  #图形显示区域
        table_area.setGeometry(
            QRect(widget1.x(), widget1.y(), widget1.width(), widget1.height()))

        self.Plot = Draw_ui(width=3, height=3, dpi=100)
        gridlayout1 = QGridLayout(table_area)  # 继承容器groupBox
        gridlayout1.addWidget(self.Plot, 0, 1)

        pic_choose_label = QLabel(self)
        pic_choose_label.move(table_area.x() + table_area.width() + 30,
                              table_area.y() + 20)
        pic_choose_label.setText("输入迷宫:")
        pic_choose_label2 = QLabel(self)
        pic_choose_label2.move(
            pic_choose_label.geometry().x(),
            pic_choose_label.y() + pic_choose_label.height() + 20)
        pic_choose_label2.setText("(1表示空格,0表示墙, 2表示陷阱, 3表示火)")

        self.maze_input = QPlainTextEdit(parent=self)
        self.maze_input.setGeometry(
            QRect(pic_choose_label2.x(),
                  pic_choose_label2.y() + pic_choose_label2.height() + 20, 300,
                  200))
        self.maze_input.setPlainText(
            '1, 0, 1, 1, 1, 1, 1,\r\n1, 1, 3, 0, 0, 1, 0,\r\n0, 0, 0, 1, 1, 1, 0,\r\n1, 1, 1, 1, 0, 0, 1,\r\n1, 0, 0, 0, 1, 1, 1,\r\n1, 0, 1, 1, 1, 2, 2,\r\n1, 1, 1, 0, 1, 1, 1,'
        )

        period_label = QLabel(parent=self)
        period_label.setText('火焰周期:')
        period_label.move(self.maze_input.x(),
                          self.maze_input.height() + self.maze_input.y() + 10)

        self.period_input = QSpinBox(parent=self)
        self.period_input.setValue(1)
        self.period_input.move(period_label.x() + period_label.width() + 15,
                               period_label.y())

        period_label2 = QLabel(parent=self)
        period_label2.setText('*2')
        period_label2.move(
            self.period_input.x() + self.period_input.width() - 40,
            self.period_input.y())

        maze_input_button = QPushButton(parent=self)
        maze_input_button.move(
            self.period_input.x() - 50,
            self.period_input.y() + self.period_input.height() + 10)
        maze_input_button.setText('确认输入')
        maze_input_button.pressed.connect(self.pic_change)

        middle_x = self.maze_input.geometry().x(
        ) + self.maze_input.geometry().width() / 2

        train_epoch_label = QLabel(parent=self)
        train_epoch_label.setText('训练次数上限:')
        train_epoch_label.move(
            self.maze_input.x(),
            maze_input_button.height() + maze_input_button.y() + 40)

        self.epoch_input = QSpinBox(parent=self)
        self.epoch_input.move(
            train_epoch_label.x() + train_epoch_label.width() + 15,
            train_epoch_label.y())
        self.epoch_input.setValue(30)

        train_epoch_label2 = QLabel(parent=self)
        train_epoch_label2.setText('*1000')
        train_epoch_label2.move(
            self.epoch_input.x() + self.epoch_input.width() - 40,
            self.epoch_input.y())

        self.solve_problem_button = QPushButton(parent=self)
        self.solve_problem_button.setText("训练")
        self.solve_problem_button.move(
            maze_input_button.x(),
            train_epoch_label.y() + train_epoch_label.height() + 10)
        self.solve_problem_button.pressed.connect(self.solve_button_pressed)

        self.solve_test = QLabel(parent=self)  # 解答过程中的信息显示
        self.solve_test.setText("正在训练。。。")
        self.solve_test.resize(250, self.solve_test.height())
        self.solve_test.move(
            middle_x - self.solve_test.geometry().width() / 2,
            self.solve_problem_button.y() +
            self.solve_problem_button.height() + 10)
        self.solve_test.setHidden(True)

        speed_choose_label = QLabel(self)
        speed_choose_label.move(
            train_epoch_label.x(),
            self.solve_test.y() + self.solve_test.height() + 10)
        speed_choose_label.setText("播放速度:")
        self.play_speed_combo = QComboBox(self)
        self.play_speed_combo.move(
            speed_choose_label.geometry().x() +
            speed_choose_label.geometry().width() + 30,
            speed_choose_label.geometry().y())
        self.play_speed_combo.addItems(["高速", "中速", "慢速"])

        play_button = QPushButton(self)
        play_button.setText("播放走迷宫过程")
        play_button.move(
            speed_choose_label.x() + 40,
            self.play_speed_combo.geometry().y() +
            self.play_speed_combo.geometry().height() + 10)
        play_button.pressed.connect(self.play_button_pressed)

    def pic_change(self):
        self.timer.stop()
        current_text = self.maze_input.toPlainText()
        rows = current_text.split('\n')
        maze_map = []
        try:
            for row in rows:
                row_sp = row.split(',')
                row_list = []
                for c in row_sp:
                    c = c.strip()
                    if len(c) == 0:
                        continue
                    else:
                        row_list.append(int(c))
                maze_map.append(row_list)
        except:
            QMessageBox.information(self, "提示", "无法解析输入",
                                    QMessageBox.Ok | QMessageBox.Close,
                                    QMessageBox.Close)
            return

        maze_len = len(maze_map[0])
        for i in range(1, len(maze_map)):
            if len(maze_map[i]) != maze_len:
                QMessageBox.information(self, "提示", "错误,每一行的列数应当相等",
                                        QMessageBox.Ok | QMessageBox.Close,
                                        QMessageBox.Close)
                return

        my_maze = Maze(maze_map=np.array(maze_map),
                       period=self.period_input.value() * 2)
        self.model = QTableModel(my_maze)

        #self.model.play_game((0, 0), 0)
        self.Plot.draw_root(self.model.my_maze, (0, 0), 1, 0, False)
        self.Plot.draw_qtable(qtable_model=self.model,
                              time_=self.model.my_maze.period -
                              1 if self.model.my_maze.period != 0 else 0,
                              fire_flag=True)

    def play_button_pressed(self):
        if self.model == None:
            QMessageBox.information(self, "提示", "请先输入迷宫",
                                    QMessageBox.Ok | QMessageBox.Close,
                                    QMessageBox.Close)
            return

        self.model.play_game((0, 0), 0)
        speed_text = self.play_speed_combo.currentText()
        self.playing_index = 0
        if speed_text == "高速":
            self.timer.start(150, self)
        elif speed_text == "中速":
            self.timer.start(500, self)
        else:
            self.timer.start(1500, self)

    def timerEvent(self, event):
        if event.timerId() == self.timer.timerId():
            period = self.model.my_maze.period
            if period != 0 and (self.playing_index % period) >= period / 2:
                fire_flag = True
            else:
                fire_flag = False

            self.Plot.draw_qtable(
                self.model, self.playing_index % period if period != 0 else 0,
                fire_flag)
            self.Plot.draw_root(self.model.my_maze, (0, 0), self.playing_index,
                                period, fire_flag)

            self.playing_index = self.playing_index + 1

            if self.playing_index >= len(self.model.my_maze.visited) + 2:
                self.playing_index = 0
                # print("up",self.playing_index)
        else:
            super(Ui_userDefine, self).timerEvent(event)

    def solve_button_pressed(self):
        if self.problem_solving:
            return
        if type(self.model) == type(None):
            QMessageBox.information(self, "提示", "请先输入迷宫",
                                    QMessageBox.Ok | QMessageBox.Close,
                                    QMessageBox.Close)
            return

        self.problem_solving = True
        self.playing_index = -1
        self.solve_test.setHidden(False)
        self.timer.stop()
        self.repaint()

        train_epoch = self.epoch_input.value() * 1000
        start_time = time.time()
        #path = "tangrams\\" + self.parent().pic_choose_combo.currentText() + ".png"
        self.model.train(output_line=self.solve_test,
                         main_ui=self,
                         epoch_N=train_epoch)
        end_time = time.time()

        QMessageBox.information(self, "提示",
                                "完成训练,用时:%.3f s" % (end_time - start_time),
                                QMessageBox.Ok | QMessageBox.Close,
                                QMessageBox.Close)

        self.Plot.draw_qtable(qtable_model=self.model,
                              time_=self.model.my_maze.period -
                              1 if self.model.my_maze.period != 0 else 0,
                              fire_flag=True)
        self.problem_solving = False
        self.solve_test.setHidden(True)
class UIUserDefine(QWidget):
    def __init__(self):
        super().__init__()
        self.model = None
        self.playing_index = -1
        self.problem_solving = False

    def init_ui(self):
        self.resize(1200, 680)

        self.timer = QBasicTimer()
        widget1 = QWidget(parent=self)
        widget1.setGeometry(QRect(30, 50, 800, 500))
        table_area = QGroupBox(parent=widget1)  # 图形显示区域
        table_area.setGeometry(
            QRect(widget1.x(), widget1.y(), widget1.width(), widget1.height()))

        self.Plot = DrawUI(width=3, height=3, dpi=100)
        gridlayout1 = QGridLayout(table_area)  # 继承容器groupBox
        gridlayout1.addWidget(self.Plot, 0, 1)

        pic_choose_label = QLabel(self)
        pic_choose_label.move(table_area.x() + table_area.width() + 30,
                              table_area.y() + 20)
        pic_choose_label.setText("Input Maze:")
        pic_choose_label.setFont(QFont("Fixed", 10))
        pic_choose_label2 = QLabel(self)
        pic_choose_label2.move(
            pic_choose_label.geometry().x(),
            pic_choose_label.y() + pic_choose_label.height() + 20)
        pic_choose_label2.setText(
            "(1 is space,0 is wall, 2 is grass, 3 is light)")
        pic_choose_label2.setFont(QFont("Fixed", 10))

        self.maze_input = QPlainTextEdit(parent=self)
        self.maze_input.setGeometry(
            QRect(pic_choose_label2.x(),
                  pic_choose_label2.y() + pic_choose_label2.height() + 20, 250,
                  150))
        self.maze_input.setPlainText(
            '1, 0, 1, 1, 1, 1, 1,\r\n1, 1, 3, 0, 0, 1, 0,\r\n0, 0, 0, 1, 1, 1, 0,\r\n1, 1, 1, 1, 0, 0, 1,\r\n1, 0, 0, 0, 1, 1, 1,\r\n1, 0, 1, 1, 1, 2, 2,\r\n1, 1, 1, 0, 1, 1, 1,'
        )

        period_label = QLabel(parent=self)
        period_label.setText('Light Period:')
        period_label.setFont(QFont("Fixed", 10))
        period_label.move(self.maze_input.x(),
                          self.maze_input.height() + self.maze_input.y() + 10)

        self.period_input = QSpinBox(parent=self)
        self.period_input.setValue(1)
        self.period_input.setFont(QFont("Fixed", 10))
        self.period_input.move(period_label.x() + period_label.width() + 15,
                               period_label.y() - 2)

        period_label2 = QLabel(parent=self)
        period_label2.setText('*2')
        period_label2.setFont(QFont("Fixed", 10))
        period_label2.move(
            self.period_input.x() + self.period_input.width() - 40,
            self.period_input.y() + 2)

        maze_input_button = QPushButton(parent=self)
        maze_input_button.move(
            period_label.x() + period_label.width() + 15,
            self.period_input.y() + self.period_input.height() + 10)
        maze_input_button.setText('Done')
        maze_input_button.setFont(QFont("Fixed", 10))
        maze_input_button.pressed.connect(self.pic_change)

        middle_x = self.maze_input.geometry().x(
        ) + self.maze_input.geometry().width() / 2

        train_epoch_label = QLabel(parent=self)
        train_epoch_label.setText('Training Count:')
        train_epoch_label.setFont(QFont("Fixed", 10))
        train_epoch_label.move(
            self.maze_input.x(),
            maze_input_button.height() + maze_input_button.y() + 40)

        self.epoch_input = QSpinBox(parent=self)
        self.epoch_input.move(
            train_epoch_label.x() + train_epoch_label.width() + 15,
            train_epoch_label.y() - 2)
        self.epoch_input.setValue(30)
        self.epoch_input.setFont(QFont("Fixed", 10))

        train_epoch_label2 = QLabel(parent=self)
        train_epoch_label2.setText('*1000')
        train_epoch_label2.setFont(QFont("Fixed", 10))
        train_epoch_label2.move(
            self.epoch_input.x() + self.epoch_input.width() - 40,
            self.epoch_input.y() + 2)

        self.solve_problem_button = QPushButton(parent=self)
        self.solve_problem_button.setText("Train Now")
        self.solve_problem_button.setFont(QFont("Fixed", 10))
        self.solve_problem_button.move(
            period_label.x() + period_label.width() + 15,
            train_epoch_label.y() + train_epoch_label.height() + 10)
        self.solve_problem_button.pressed.connect(self.solve_button_pressed)

        self.solve_test = QLabel(parent=self)  # 解答过程中的信息显示
        self.solve_test.setText("Training...")
        self.solve_test.setFont(QFont("Fixed", 10))
        self.solve_test.resize(250, self.solve_test.height())
        self.solve_test.move(
            middle_x - self.solve_test.geometry().width() / 2,
            self.solve_problem_button.y() +
            self.solve_problem_button.height() + 10)
        self.solve_test.setHidden(True)

        speed_choose_label = QLabel(self)
        speed_choose_label.move(
            train_epoch_label.x(),
            self.solve_test.y() + self.solve_test.height() + 10)
        speed_choose_label.setText("Play Speed:")
        speed_choose_label.setFont(QFont("Fixed", 10))
        self.play_speed_combo = QComboBox(self)
        self.play_speed_combo.move(
            period_label.x() + period_label.width() + 15,
            speed_choose_label.geometry().y() - 2)
        self.play_speed_combo.addItems(["High", "Middle", "Low"])
        self.play_speed_combo.setFont(QFont("Fixed", 10))

        play_button = QPushButton(self)
        play_button.setText("Play Result Now!")
        play_button.setFont(QFont("Fixed", 10))
        play_button.move(
            period_label.x() + period_label.width() + 15,
            self.play_speed_combo.geometry().y() +
            self.play_speed_combo.geometry().height() + 10)
        play_button.pressed.connect(self.play_button_pressed)

    def pic_change(self):
        self.timer.stop()
        current_text = self.maze_input.toPlainText()
        rows = current_text.split('\n')
        maze_map = []
        try:
            for row in rows:
                row_sp = row.split(',')
                row_list = []
                for c in row_sp:
                    c = c.strip()
                    if len(c) == 0:
                        continue
                    else:
                        row_list.append(int(c))
                maze_map.append(row_list)
        except:
            QMessageBox.information(self, "Warning", "Invalid Input.",
                                    QMessageBox.Ok | QMessageBox.Close,
                                    QMessageBox.Close)
            return

        maze_len = len(maze_map[0])
        for i in range(1, len(maze_map)):
            if len(maze_map[i]) != maze_len:
                QMessageBox.information(
                    self, "Warning",
                    "Error,each row should have the same number of columns.",
                    QMessageBox.Ok | QMessageBox.Close, QMessageBox.Close)
                return

        my_maze = Maze(maze_map=np.array(maze_map),
                       period=self.period_input.value() * 2)
        self.model = QTableModel(my_maze)

        # self.model.play_game((0, 0), 0)
        self.Plot.draw_root(self.model.my_maze, (0, 0), 1, 0, False)
        self.Plot.draw_qtable(qtable_model=self.model,
                              time_=self.model.my_maze.period -
                              1 if self.model.my_maze.period != 0 else 0,
                              fire_flag=True)

    def play_button_pressed(self):
        if self.model == None:
            QMessageBox.information(self, "Tip",
                                    "Please input the maze first.",
                                    QMessageBox.Ok | QMessageBox.Close,
                                    QMessageBox.Close)
            return

        self.model.play_game((0, 0), 0)
        speed_text = self.play_speed_combo.currentText()
        self.playing_index = 0
        if speed_text == "High":
            self.timer.start(100, self)
        elif speed_text == "Middle":
            self.timer.start(500, self)
        else:
            self.timer.start(1500, self)

    def timerEvent(self, event):
        if event.timerId() == self.timer.timerId():
            period = self.model.my_maze.period
            if period != 0 and (self.playing_index % period) >= period / 2:
                fire_flag = True
            else:
                fire_flag = False

            self.Plot.draw_qtable(
                self.model, self.playing_index % period if period != 0 else 0,
                fire_flag)
            self.Plot.draw_root(self.model.my_maze, (0, 0), self.playing_index,
                                period, fire_flag)

            self.playing_index = self.playing_index + 1

            if self.playing_index >= len(self.model.my_maze.visited) + 2:
                self.playing_index = 0
                # print("up",self.playing_index)
        else:
            super(UIUserDefine, self).timerEvent(event)

    def solve_button_pressed(self):
        if self.problem_solving:
            return
        if type(self.model) == type(None):
            QMessageBox.information(self, "Tip",
                                    "Please input the maze first.",
                                    QMessageBox.Ok | QMessageBox.Close,
                                    QMessageBox.Close)
            return

        self.problem_solving = True
        self.playing_index = -1
        self.solve_test.setHidden(False)
        self.timer.stop()
        self.repaint()

        train_epoch = self.epoch_input.value() * 1000
        start_time = time.time()
        # path = "tangrams\\" + self.parent().pic_choose_combo.currentText() + ".png"
        self.model.train(output_line=self.solve_test,
                         main_ui=self,
                         epoch_N=train_epoch)
        end_time = time.time()

        QMessageBox.information(
            self, "Tip",
            "Training finished,spend:%.3f s" % (end_time - start_time),
            QMessageBox.Ok | QMessageBox.Close, QMessageBox.Close)

        self.Plot.draw_qtable(qtable_model=self.model,
                              time_=self.model.my_maze.period -
                              1 if self.model.my_maze.period != 0 else 0,
                              fire_flag=True)
        self.problem_solving = False
        self.solve_test.setHidden(True)