python - 如何使用 python PyQt5 将 gif 放入 gui 中

标签 python pyqt5

这个程序是一个交通灯程序,但我想在窗口的右侧空间放置一个 gif,当颜色为绿色时,它将显示一个行走的人 gif,当颜色为红色或黄色时,将显示一个停止 gif,所以我尝试使用 QMovie我得到的结果好坏参半,但仍然出现错误,或者 gif 不会出现在窗口中,您能帮助我吗?

from itertools import cycle
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QTimer,Qt,QPoint
from PyQt5.QtWidgets import QApplication,QMainWindow
from PyQt5.QtGui import QPainter,QColor,QMovie
class TrafficLight(QMainWindow):
    def __init__(self,parent = None):
        super(TrafficLight, self).__init__(parent)
        self.setWindowTitle("TrafficLight ")
        self.traffic_light_color1 = cycle(\[
            QColor('red'),
            QColor('gray'),
            QColor('gray')
        \])
        self.traffic_light_color2 = cycle(\[
            QColor('gray'),
            QColor('yellow'),
            QColor('gray')
        \])
        self.traffic_light_color3 = cycle(\[
            QColor('gray'),
            QColor('gray'),
            QColor('green')
        \])

        self._current_color1 = next(self.traffic_light_color1)
        self._current_color2 = next(self.traffic_light_color2)
        self._current_color3 = next(self.traffic_light_color3)
        timer = QTimer(self, timeout=self.change_color)
        x = 0
        if x == 0 :
            self.movie1 = QMovie("Walking-man2[enter image description here][1].gif")
            self.movie1.frameChanged.connect(self.repaint)
            self.movie1.start()
            timer.start(30*100)
            x = 1
        elif x == 1 :
            self.movie1 = QMovie("tenor(1).gif")
            self.movie1.frameChanged.connect(self.repaint)
            self.movie1.start()
            timer.start(10*100)
            x = 2
        elif x == 2:
            self.movie1 = QMovie("tenor(1).gif")
            self.movie1.frameChanged.connect(self.repaint)
            self.movie1.start()
            timer.start(40*100)
            x = 0
        self.resize(700, 510)

    @QtCore.pyqtSlot()
    def change_color(self):
        self._current_color1 = next(self.traffic_light_color1)
        self._current_color2 = next(self.traffic_light_color2)
        self._current_color3 = next(self.traffic_light_color3)
        self.update()

    def paintEvent(self, event):
        p1 = QPainter(self)
        p1.setBrush(self._current_color1)
        p1.setPen(Qt.black)
        p1.drawEllipse(QPoint(125, 125), 50, 50)

        p2 = QPainter(self)
        p2.setBrush(self._current_color2)
        p2.setPen(Qt.black)
        p2.drawEllipse(QPoint(125, 250),50,50)

        p3 = QPainter(self)
        p3.setBrush(self._current_color3)
        p3.setPen(Qt.black)
        p3.drawEllipse(QPoint(125, 375),50,50)

        currentFrame = self.movie1.currentPixmap()
        frameRect = currentFrame.rect()
        frameRect.moveCenter(self.rect().center())
        if frameRect.intersects(event.rect()):
            painter = QPainter(self)
            painter.drawPixmap(frameRect.left(), frameRect.top(), currentFrame)


if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    w = TrafficLight()
    w.show() 
    sys.exit(app.exec_())

最佳答案

将一种状态更改为另一种状态的逻辑可以使用有限状态机(FSM)来实现,幸运的是Qt使用The State Machine Framework来实现它。 :

from functools import partial
from PyQt5 import QtCore, QtGui, QtWidgets

class LightWidget(QtWidgets.QWidget):
    def __init__(self, color, parent=None):
        super(LightWidget, self).__init__(parent)
        self._state = False
        self._color = color
        self.setFixedSize(150, 150)

    @QtCore.pyqtSlot()
    def turnOn(self):
        self._state = True
        self.update()

    @QtCore.pyqtSlot()
    def turnOff(self):
        self._state = False
        self.update()

    def paintEvent(self, event):
        color = self._color if self._state else QtGui.QColor('gray')
        painter = QtGui.QPainter(self)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        painter.setPen(QtCore.Qt.black)
        painter.setBrush(color)
        painter.drawEllipse(self.rect())

class TrafficLightWidget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(TrafficLightWidget, self).__init__(parent)
        hlay = QtWidgets.QHBoxLayout(self)
        container = QtWidgets.QWidget()
        container.setStyleSheet('''background-color : black''')
        vlay = QtWidgets.QVBoxLayout(container)
        self.m_red = LightWidget(QtGui.QColor("red"))
        self.m_yellow = LightWidget(QtGui.QColor("yellow"))
        self.m_green = LightWidget(QtGui.QColor("green"))
        vlay.addWidget(self.m_red)
        vlay.addWidget(self.m_yellow)
        vlay.addWidget(self.m_green)
        hlay.addWidget(container, alignment=QtCore.Qt.AlignCenter)
        self.label = QtWidgets.QLabel("Test", alignment=QtCore.Qt.AlignCenter)
        hlay.addWidget(self.label, 1)

        red_to_yellow = createLightState(self.m_red, 30*1000, partial(self.change_gif, "gif_red.gif"))
        yellow_to_green = createLightState(self.m_yellow, 20*1000, partial(self.change_gif, "gif_yellow.gif"))
        green_to_yellow = createLightState(self.m_green, 40*1000, partial(self.change_gif, "gif_green.gif"))
        yellow_to_red = createLightState(self.m_yellow, 20*1000, partial(self.change_gif, "gif_yellow.gif"))

        red_to_yellow.addTransition(red_to_yellow.finished, yellow_to_green)
        yellow_to_green.addTransition(yellow_to_green.finished, green_to_yellow)
        green_to_yellow.addTransition(green_to_yellow.finished, yellow_to_red)
        yellow_to_red.addTransition(yellow_to_red.finished, red_to_yellow)

        machine = QtCore.QStateMachine(self)
        machine.addState(red_to_yellow)
        machine.addState(yellow_to_green)
        machine.addState(green_to_yellow)
        machine.addState(yellow_to_red)
        machine.setInitialState(red_to_yellow)
        machine.start()

    @QtCore.pyqtSlot()
    def change_gif(self, gif):
        last_movie = self.label.movie()
        movie = QtGui.QMovie(gif)
        self.label.setMovie(movie)
        movie.start()
        if last_movie is not None:
            last_movie.deleteLater()

def createLightState(light, duration, callback):
    lightState = QtCore.QState()
    timer = QtCore.QTimer(
        lightState, 
        interval=duration, 
        singleShot=True
    )
    timing = QtCore.QState(lightState)
    timing.entered.connect(light.turnOn)
    timing.entered.connect(callback)
    timing.entered.connect(timer.start)
    timing.exited.connect(light.turnOff)
    done = QtCore.QFinalState(lightState)
    timing.addTransition(timer.timeout, done)
    lightState.setInitialState(timing)
    return lightState


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = TrafficLightWidget()
    w.resize(640, 480)
    w.show()
    sys.exit(app.exec_())

关于python - 如何使用 python PyQt5 将 gif 放入 gui 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55104692/

相关文章:

python - 当安装多个版本的 python 时,tox 使用错误版本的 pip

python - 禁用从 GUI (PyQt) 打开 cmd

python - 从 PyQt GUI 连接到串口

python - 删除Qlabel中不必要的空白

python - 为什么在mac上使用PyQt5不能添加图标?

Python:强制 pprint 将 unicode 字符串显示为字符串?

javascript - scrapy:从 javascript 生成的表单中抓取数据

python - 获取 QPolygonF 的点

python - matplotlib 饼图中缺少标签

python - Django makemigrations 有效,迁移失败,显示 "django.db.utils.IntegrityError: NOT NULL constraint failed"