pyqt5 gui在while循环中冻结

pyqt5 gui freezing in while loop

我正在编写 python gui 应用程序来处理图像并从串行端口发送图像颜色并显示结果,但不幸的是我的 gui 冻结了。我尝试使用 QApllication.processEvents 并且它有效,但我的程序速度很慢,速度对我来说非常重要,每一秒一次迭代都应该完成。 这是我的代码:

        while self.knot <= knotter_width:

            color_to_send = []
            for i in range(1, number_of_knotter + 1):
                color_to_send.append(self.baft["knotters"][i][self.lay][self.knot])

            # send color numbers

            # receive color feedback

            self.knot = self.knot + 1

            if self.knot > knotter_width:
                break

            self.config_write()
            self.knotters_status() # gui update function
            QCoreApplication.processEvents()

和knotters_status函数:

    def knotters_status(self):
        try:
            for i in range(number_of_knotter):
                self.knotters_status_dict[i].deleteLater()
        except:
            pass

        try:
            self.baft
        except:
            self.status.setAlignment(Qt.Alignment(132))
            status_gui_font_error = QFont("Arial", 43)
            status_gui_font_error.setBold(True)
            self.status.setFont(status_gui_font_error)
            self.status.setText("فایل بافت لود نشده است!")
            return

        self.knotters_status_dict = {}


        # size calculation:
        width_geo_start_point = 50
        width_step = int((self.status_width - 50)/number_of_knotter)
        self.each_knotters_sector_unit_height = int(self.status_height / 7)
        knotters_status_font_size = int(self.each_knotters_sector_unit_height / 1.5)
        knotters_status_font = QFont("Arial", knotters_status_font_size)
        knotters_status_font.setBold(True)


        for i in range(number_of_knotter):
            self.knotters_status_dict[i] = QLabel(self.status)
            self.knotters_status_dict[i].setGeometry((width_geo_start_point + width_step * (number_of_knotter - i - 1)),
                                                      0,
                                                      width_step,
                                                      self.status_height)
            self.knotters_status_dict[i].setStyleSheet("border: 1px solid black;"
                                                       "background-color: whitesmoke")
            self.knotters_status_dict[i].setAlignment(Qt.Alignment(36))
            self.knotters_status_dict[i].setFont(knotters_status_font)
            color_number = self.baft["knotters"][i + 1][self.lay][self.knot] + 1
            self.knotters_status_dict[i].setText("بافنده {}\nلای {}\nگره {}\nرنگ {}".format(i,
                                                                                           self.lay,
                                                                                           self.knot,
                                                                                           color_number))

            colors_width = width_step // 4
            y = self.each_knotters_sector_unit_height * 4 + self.each_knotters_sector_unit_height // 3
            colors = {}
            if self.lay != 1 and self.lay != self.baft["height"]:
                if self.knot != 1 and self.knot != knotter_width:
                    for j in range(2):
                        colors[j] = {}
                        x = colors_width // 4
                        for k in range(1,-2,-1):
                            target_lay = self.lay - j
                            target_knot = self.knot + k
                            colors[j][k] = QLabel(self.knotters_status_dict[i])
                            colors[j][k].setGeometry(x,
                                                     y,
                                                     colors_width,
                                                     self.each_knotters_sector_unit_height)
                            color_rgb = self.baft["color table"][self.baft["knotters"][i+1][target_lay][target_knot]+1]
                            colors[j][k].setStyleSheet("border: 1px solid black;"
                                                       "border-radius: 10px;"
                                                       "background-color: rgb({}, {}, {});".format \
                                                       (color_rgb[0],
                                                        color_rgb[1],
                                                        color_rgb[2]))
                            colors[j][k].show()
                            x = x + colors_width + colors_width // 4
                         y = y + int(self.each_knotters_sector_unit_height * 4 / 3)
                elif self.knot == 1:
                pass
                elif self.knot == knotter_width:
                    pass
            elif self.lay == 1:
                pass
            elif self.lay == self.baft["height"]:
                pass

            self.knotters_status_dict[i].show()

经过我的研究,我发现了这个但也不起作用:

class Worker(QObject):

progress = pyqtSignal(int)
gui_update = pyqtSignal()
finish = pyqtSignal(bool)
ex = pyqtSignal()

@pyqtSlot(int, int, dict)
def run(self, knot, lay, baft):

    # send finish order

    # recieve finish feedback

    while knot <= knotter_width:
        color_to_send = []
        for i in range(1, number_of_knotter + 1):
            color_to_send.append(baft["knotters"][i][lay][knot])

        # send color numbers

        # receive color feedback

        if knot < knotter_width:
            knot = knot + 1
        else:
            break


        self.progress.emit(knot)
        self.gui_update.emit()

    self.finish.emit(True)

    # send finish order

    #reveive finish feedback

    self.ex.emit()

并设置线程:

    self.thrd = QThread()
    self.worker = Worker()
    self.worker.moveToThread(self.thrd)
    self.thrd.started.connect(lambda: self.worker.run(self.knot, self.lay, self.baft))
    self.worker.progress.connect(self.progress)
    self.worker.gui_update.connect(self.knotters_status)
    self.worker.finish.connect(self.finished)
    self.worker.ex.connect(self.thrd.quit)
    self.worker.ex.connect(self.worker.deleteLater)
    self.thrd.finished.connect(self.thrd.deleteLater)

    self.thrd.start()

经过几天的研究,我找到了这个解决方案: 首先,您必须编写 class 并从 QThread class 继承,然后使用信号和槽重新实现 运行 方法,然后您从 class 创建对象,紧接着你应该调用 processEvents() 方法来引用你的 QApplication 对象。在这种情况下,它不会导致速度变慢,而且它非常适合 mopre 细节你可以参考我的另一个问题和答案,你可以点击