Текст Pyqt Marquee висит через несколько часов - PullRequest
0 голосов
/ 31 октября 2018

Я использую следующий код для создания прокручиваемого текста с использованием pyqt. Также я создаю прямоугольную рамку в своем интерфейсе, используя QPainter. Проблема в том, что код как таковой работает нормально, но через некоторое время зависает. Сообщение перестает прокручиваться, пока функционирует другой интерфейс пользователя. Я использовал код из предыдущего вопроса переполнения стека для прокрутки текста Marquee effect . Ниже приведена часть моего кода

class MarqueeLabel(QtGui.QLabel):
    def __init__(self, parent=None):
        QtGui.QLabel.__init__(self, parent)
        self.px = 0
        self.py = 15
        self._direction = Qt.RightToLeft #Qt.LeftToRight
        self.setWordWrap(True)
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update)
        self.timer.start(20)
        self._speed = 2
        self.textLength = 0
        self.fontPointSize = 0
        self.setAlignment(Qt.AlignVCenter)
        self.setFixedHeight(self.fontMetrics().height())

    def setFont(self, font, size):
        newfont = QtGui.QFont(font, size, QtGui.QFont.Bold)
        QtGui.QLabel.setFont(self, newfont)
        self.setFixedHeight(self.fontMetrics().height())

    def updateCoordinates(self):
        align = self.alignment()
        if align == Qt.AlignTop:
            self.py = 10
        elif align == Qt.AlignBottom:
            self.py = self.height() - 10
        elif align == Qt.AlignVCenter:
            self.py = self.height() / 2
        self.fontPointSize = self.font().pointSize() / 2
        self.textLength = self.fontMetrics().width(self.text())

    def setAlignment(self, alignment):
        self.updateCoordinates()
        QtGui.QLabel.setAlignment(self, alignment)

    def resizeEvent(self, event):
        self.updateCoordinates()
        QtGui.QLabel.resizeEvent(self, event)

    def paintEvent(self, event):
        painter = QPainter(self)
        if self._direction == Qt.RightToLeft:
            self.px -= self.speed()
            if self.px <= -self.textLength:
                self.px = self.width()
        else:
            self.px += self.speed()
            if self.px >= self.width():
                self.px = -self.textLength
        painter.drawText(self.px, self.py + self.fontPointSize, self.text())
        painter.translate(self.px, 0)

    def speed(self):
        return self._speed

    def setSpeed(self, speed):
        self._speed = speed

    def setDirection(self, direction):
        self._direction = direction
        if self._direction == Qt.RightToLeft:
            self.px = self.width() - self.textLength
        else:
            self.px = 0
        self.update()

    def pause(self):
        self.timer.stop()

    def unpause(self):
        self.timer.start()

class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        self.signalUpdateUI()
    def signalUpdateUI(self):
        updateUIThread = Thread(target=self.updateUI)
        updateUIThread.daemon = True
        updateUIThread.start()
    def updateUI(self):
        while(1==1):
            #update some text color and contents
            #update marquee label contents
            self.update()
            sleep(2)
    def paintEvent(self, event):
        QWidget.paintEvent(self, event)
        painter = QPainter(self)
        pen = QtGui.QPen(QtCore.Qt.black, 2, QtCore.Qt.SolidLine)
        painter.setPen(pen)
        painter.drawLine(0,190, 1920,190)
        painter.drawLine(0,300, 1920,300)
        painter.drawLine(0,840, 1920,840)
        painter.drawLine(0,930, 1920,930)

        # Reactangle Box Settings
        painter.setPen(self._rectBoxLine_color)
        painter.setBrush(self._rectBox_color)
        rect = QRect(1430,300,470,535)

        painter.drawRect(rect)
        painter.setFont(QtGui.QFont('Consolas', 60, QtGui.QFont.Bold))
        painter.setPen(QtGui.QColor(0, 0, 0))      
        painter.drawText(QRect(1430,300,470,535), QtCore.Qt.AlignCenter, self._rect_text)

Я не знаю, почему сообщение прокрутки останавливается через несколько часов, даже если функционирует другой интерфейс пользователя.

1 Ответ

0 голосов
/ 31 октября 2018

Реализация marqueLabel эффективна, поэтому я не думаю, что это является причиной ошибки, с другой стороны, код, который показывается, также не является исполняемым, но что он показывает, вы можете заметить неправильное использование потоков для периодических задач, в случае с графическим интерфейсом запрещено напрямую изменять графический интерфейс из другого потока, кроме того, что выполняемая задача не является тяжелой, поэтому вы должны использовать вместо нее QTimer.

from PyQt4 import QtCore, QtGui

class MarqueeLabel(QtGui.QLabel):
    def __init__(self, parent=None):
        super(MarqueeLabel, self).__init__(parent)
        self.px = 0
        self.py = 15
        self._direction = QtCore.Qt.RightToLeft #Qt.LeftToRight
        self.setWordWrap(True)
        self.timer = QtCore.QTimer(self, interval=20)
        self.timer.timeout.connect(self.update)
        self.timer.start()
        self._speed = 2
        self.textLength = 0
        self.fontPointSize = 0
        self.setAlignment(QtCore.Qt.AlignVCenter)
        self.setFixedHeight(self.fontMetrics().height())

    def setFont(self, font, size):
        newfont = QtGui.QFont(font, size, QtGui.QFont.Bold)
        QtGui.QLabel.setFont(self, newfont)
        self.setFixedHeight(self.fontMetrics().height())

    def updateCoordinates(self):
        align = self.alignment()
        if align == QtCore.Qt.AlignTop:
            self.py = 10
        elif align == QtCore.Qt.AlignBottom:
            self.py = self.height() - 10
        elif align == QtCore.Qt.AlignVCenter:
            self.py = self.height() / 2
        self.fontPointSize = self.font().pointSize() / 2
        self.textLength = self.fontMetrics().width(self.text())

    def setAlignment(self, alignment):
        self.updateCoordinates()
        QtGui.QLabel.setAlignment(self, alignment)

    def resizeEvent(self, event):
        self.updateCoordinates()
        QtGui.QLabel.resizeEvent(self, event)

    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        if self._direction == QtCore.Qt.RightToLeft:
            self.px -= self.speed()
            if self.px <= -self.textLength:
                self.px = self.width()
        else:
            self.px += self.speed()
            if self.px >= self.width():
                self.px = -self.textLength
        painter.drawText(self.px, self.py + self.fontPointSize, self.text())
        painter.translate(self.px, 0)

    def speed(self):
        return self._speed

    def setSpeed(self, speed):
        self._speed = speed

    def setDirection(self, direction):
        self._direction = direction
        if self._direction == Qt.RightToLeft:
            self.px = self.width() - self.textLength
        else:
            self.px = 0
        self.update()

    def pause(self):
        self.timer.stop()

    def unpause(self):
        self.timer.start()

class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self._rectBoxLine_color = QtGui.QColor(QtCore.Qt.green)
        self._rectBox_color = QtGui.QBrush(QtCore.Qt.blue)
        self._rect_text = "_rect_text"

        self.marquee = MarqueeLabel(self)
        self.signalUpdateUI()

    def signalUpdateUI(self):
        timer = QtCore.QTimer(self, interval=2000)
        timer.timeout.connect(self.updateUI)
        timer.start()
        self.updateUI()

    def updateUI(self):
            #update some text color and contents
            #update marquee label contents
            self.marquee.setText(QtCore.QDateTime.currentDateTime().toString())
            self.update()

    def paintEvent(self, event):
        super(MainWindow, self).paintEvent(event)
        painter = QtGui.QPainter(self)
        pen = QtGui.QPen(QtCore.Qt.black, 2, QtCore.Qt.SolidLine)
        painter.setPen(pen)
        painter.drawLine(0,190, 1920,190)
        painter.drawLine(0,300, 1920,300)
        painter.drawLine(0,840, 1920,840)
        painter.drawLine(0,930, 1920,930)

        # Reactangle Box Settings
        painter.setPen(self._rectBoxLine_color)
        painter.setBrush(self._rectBox_color)
        rect = QtCore.QRect(1430,300,470,535)

        painter.drawRect(rect)
        painter.setFont(QtGui.QFont('Consolas', 60, QtGui.QFont.Bold))
        painter.setPen(QtGui.QColor(0, 0, 0))      
        painter.drawText(QtCore.QRect(1430,300,470,535), QtCore.Qt.AlignCenter, self._rect_text)


if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())
...