简体   繁体   English

如何使用python PyQt5将gif放入gui

[英]How to put a gif in gui using python PyQt5

This program is a trafficlight program but i want to put a gif on the right space of the window that will show a walking man gif when the color is green and a stop gif when in red or yellow so I tried to use QMovie which I get mixed results and still ended up in an error or the gif won't appear at the window can you please help me? 这个程序是一个交通灯程序,但我想在窗口的正确空间放一个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_())

The logic of changing one state to another can be implemented with a Finite State Machine (FSM), and fortunately Qt implements it using The State Machine Framework : 可以使用有限状态机(FSM)实现将一个状态更改为另一个状态的逻辑,幸运的是Qt使用状态机框架实现它:

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_())

Though the answer ain't as fancy as eyllanesc's... You can make the ellipse depend on a variable color, then change the stored variable color and call update(). 虽然答案并不像eyllanesc那样华丽......你可以让椭圆依赖于变量颜色,然后改变存储的变量颜色并调用update()。 The gif can be displayed using a label 可以使用标签显示gif

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(QtWidgets.QWidget):
    def __init__(self,parent = None):
        super(TrafficLight, self).__init__(parent)
        self.setWindowTitle("TrafficLight ")
        layout = QtWidgets.QHBoxLayout()
        self.setLayout(layout)
        self.lblGif = QtWidgets.QLabel()
        layout.addSpacing(300)
        layout.addWidget(self.lblGif)

        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.changeLight)
        self.timer.start(3000)

        self.resize(700, 510)
        self.x = 0
        self.changeLight()

    def changeLight(self):
        if self.x == 0 :
            self.color1 = QColor('red')
            self.color2 = QColor('grey')
            self.color3 = QColor('grey')
            self.loadGif('wait.gif')
            self.x = 1

        elif self.x == 1 :
            self.color1 = QColor('grey')
            self.color2 = QColor('yellow')
            self.color3 = QColor('grey')
            self.loadGif('almost.gif')
            self.x = 2

        elif self.x == 2:
            self.color1 = QColor('grey')
            self.color2 = QColor('grey')
            self.color3 = QColor('green')
            self.loadGif('walk.gif')
            self.x = 0
        self.update()

    def loadGif(self, path):
        movie = QtGui.QMovie(path)
        self.lblGif.setMovie(movie)
        movie.start()

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

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

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM