首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >未在不同类中使用信号和插槽PyQt5定义的Url

未在不同类中使用信号和插槽PyQt5定义的Url
EN

Stack Overflow用户
提问于 2019-12-03 14:25:43
回答 1查看 126关注 0票数 1

我试图使用线程并行运行一个带有参数的视频,所以当我点击SD按钮时,它激活了TP1和TP2按钮,每个按钮都有一个不同的Url。

我想显示视频,启动ProgressBar,并在最后显示结果。

代码语言:javascript
复制
from multiprocessing import Process

import sys
import json
import shlex
import threading
import subprocess
import webbrowser
from QLed import QLed
from functools import partial
from PyQt5.QtGui import QColor,QFont
from PyQt5.QtGui import QIcon, QPixmap
from PyQt5.QtGui import QPainter, QPen
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QPainter, QColor, QPen
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtCore import QDir, Qt, QUrl, QSize, QPoint, QTimer
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QMainWindow
from PyQt5 import QtCore, QtGui, QtWidgets, QtMultimedia, QtMultimediaWidgets
from PyQt5.QtWidgets import (QWidget, QPushButton, QApplication,QGridLayout, QLCDNumber)
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout, QGridLayout, QLCDNumber





class Analyzer(QtCore.QObject):


    result_ready = QtCore.pyqtSignal(object)

    def do_work(self, myurl):


        cmd = "ffprobe -v quiet -print_format json -show_streams"
        args = shlex.split(cmd)

        args.append(myurl)

        ffprobeOutput = subprocess.check_output(args).decode('utf-8')
        ffprobeOutput = json.loads(ffprobeOutput)

        result = ffprobeOutput['streams'][0]
        self.result_ready.emit(result)



class MainProg(QtWidgets.QMainWindow):

    def __init__(self):


        super(MainProg, self).__init__()

        self.resize(870, 525)
        self.centralwidget = QtWidgets.QWidget(self)
        self.centralwidget.setObjectName("centralwidget")

        ############################      The Viedeo and frame  ######

        self.frame = QtWidgets.QFrame(self)
        self.frame.setGeometry(QtCore.QRect(450, 40, 391, 291))
        self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame.setFrameShadow(QtWidgets.QFrame.Raised)

        self.mediaPlayer = QtMultimedia.QMediaPlayer(self.frame)
        self.viewer1 = QtMultimediaWidgets.QVideoWidget(self.frame)
        self.mediaPlayer.setVideoOutput(self.viewer1)
        layout1 = QtWidgets.QGridLayout(self.frame)
        layout1.addWidget(self.viewer1, 0, 0, 1, 2)
       #############################################################

        self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
        self.progressBar.setGeometry(QtCore.QRect(110, 470, 143, 25))
        self.progressBar.setProperty("value", 0)
        self.progressBar.setTextVisible(True)

        self.lcd = QtWidgets.QLCDNumber(self.centralwidget)
        self.lcd.setGeometry(QtCore.QRect(220, 50, 146, 50))
        self.lcd1 = QtWidgets.QLCDNumber(self.centralwidget)
        self.lcd1.setGeometry(QtCore.QRect(220, 100, 146, 50))
        self.lcd2 = QtWidgets.QLCDNumber(self.centralwidget)
        self.lcd2.setGeometry(QtCore.QRect(220, 150, 146, 50))
        self.lcd3 = QtWidgets.QLCDNumber(self.centralwidget)
        self.lcd3.setGeometry(QtCore.QRect(220, 200, 146, 50))
        self.lcd4 = QtWidgets.QLCDNumber(self.centralwidget)
        self.lcd4.setGeometry(QtCore.QRect(220, 250, 146, 50))
        self.lcd5 = QtWidgets.QLCDNumber(self.centralwidget)
        self.lcd5.setGeometry(QtCore.QRect(220, 300, 146, 50))
        self.lcd6 = QtWidgets.QLCDNumber(self.centralwidget)
        self.lcd6.setGeometry(QtCore.QRect(220, 350, 146, 50))


        self.txtt = QtWidgets.QLabel(self.centralwidget)
        self.txtt.setFont(QFont('Arial', 12))
        self.txtt.setGeometry(QtCore.QRect(20, 0, 300, 400))

        self.txtt.setText("Video"
                          "\nCode Name .................."
                          "\n\nHorizont........................"
                          "\n\nVertical.........................."
                          "\n\nDisplay Aspect Ratio......"
                          "\n\nRefrence........................."
                          "\n\nB frames........................."
                          "\n\nStart Bits......................."
                          "\n\nSample Aspect ratio......."
                          "\n\nBit Rate.........................")

        self.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(self)
        self.statusbar.setObjectName("statusbar")
        self.setStatusBar(self.statusbar)




       #########################The buttons#################################

        self.AASD = QtWidgets.QToolButton(self)
        self.AASD.setGeometry(QtCore.QRect(140, 20, 31, 32))
        self.AASD.setObjectName("AASD")
        self.AASD.setText("SD")
        self.AASD.clicked.connect(self.funcchoos)
        QTimer.singleShot(5000, lambda: self.AASD.setDisabled(False))

        self.Testpunk1 = QtWidgets.QToolButton(self)
        self.Testpunk1.setGeometry(QtCore.QRect(150, 400, 31, 32))

        self.Testpunk2 = QtWidgets.QToolButton(self)
        self.Testpunk2.setGeometry(QtCore.QRect(150, 430, 31, 32))

        self.Testpunk1.setText("TP1")
        self.Testpunk2.setText("TP2")

        self.Testpunk1.setObjectName("TP1")
        self.Testpunk2.setObjectName("TP2")

        self.Tp1 = QLed(self, onColour=QLed.Orange, shape=QLed.Circle)
        self.Tp1.setGeometry(QtCore.QRect(185, 415, 25, 25))
        self.Tp1.value = False
    ########################### the functions############################

    def funcchoos (self):

        QtCore.QTimer.singleShot(500, self.TPLed) # Using timer as QLed uses it in its tests

        if self.sender().objectName() == "AASD":
            self.Testpunk1.clicked.connect(self.MyUrl)
            self.Testpunk2.clicked.connect(self.MyUrl)
            return

    def MyUrl(self):
        TP1 = "293.168.1.6:1115"
        TP2 = "239.168.1.7:1116"


        if self.sender().objectName() == "TP1":
            myurl = TP1
            print("TP1 is playing")
            self.dep3(myurl)

            return
        if self.sender().objectName() == "TP2":
            myurl = TP2
            self.dep3(myurl)

            print(myurl)
            print("TP2 is playing")
            return

##############################################################
    def TPLed(self):
        self.Tp1.setValue(True)  # the LED ON code


#########################################################################

    def dep3(self,myurl):
        # set progress bar to undetermined state and disable button
        self.progressBar.setRange(0,0)
        self.Testpunk1.setEnabled(False)
        self.mediaPlayer.setMedia(QMediaContent(QUrl(myurl)))
        self.mediaPlayer.play()
        # create thread for doing heavy work
        self.thread = QtCore.QThread()
        self.worker = Analyzer()
        self.worker.moveToThread(self.thread)
        self.thread.started.connect(self.worker.do_work(myurl))
        self.thread.finished.connect(self.worker.deleteLater)
        self.worker.result_ready.connect(self.process_result)
        self.worker.result_ready.connect(self.worker.do_work(myurl))


        self.thread.start()

    def process_result(self, result):

        codec_name = result['codec_name']
        width = result['width']
        height = result['height']
        display_aspect_ratio = result['display_aspect_ratio']
        sample_aspect_ratio = result['sample_aspect_ratio']
        refs = result['refs']
        has_b_frames = result['has_b_frames']

        self.lcd.display(has_b_frames)
        self.lcd1.display(codec_name)
        self.lcd2.display(width)
        self.lcd3.display(height)
        self.lcd4.display(display_aspect_ratio)
        self.lcd5.display(sample_aspect_ratio)
        self.lcd6.display(refs)

        # reset progress bar and push button
        self.progressBar.setRange(0,100)
        self.progressBar.setValue(100)
        self.pushButton.setEnabled(True)



        print("done!!")



if __name__ == "__main__":
    import sys



    app = QtWidgets.QApplication(sys.argv)


    player = MainProg()
    player.show()
    sys.exit(app.exec_())
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-12-03 16:10:33

主要的问题是,当您使用:

代码语言:javascript
复制
foo.signal.connect(function(args))

等于

代码语言:javascript
复制
value = function(args)
foo.signal.connect(value)

这会导致错误,因为connect需要一个可调用的,而且在您的情况下,值不引起错误。

通常的解决方案是使用lambda或partials,但是第一个方法将导致函数在主线程中执行,因为它是在该线程中调用的,因此它必须被丢弃,而非部分只添加参数。

  • lambda:

代码语言:javascript
复制
foo.signal.connect(lambda *_, args=args : function(args))

  • functools.partial

代码语言:javascript
复制
foo.signal.connect(functools.partial(function, args))

此外,还存在其他错误,例如每次调用"funcchoos“时,都会在"TestpunkX”和MyUrl之间创建新的连接,从而导致每次按"TestpunkX“时,调用"MyUrl”的次数与"funcchoos被调用“的次数一样多。

考虑到上述情况,我重写了您的代码,因为可能有其他错误。

代码语言:javascript
复制
from functools import partial
import json
import shlex
import subprocess
import sys


from QLed import QLed

from PyQt5 import QtCore, QtGui, QtWidgets, QtMultimedia, QtMultimediaWidgets


class Analyzer(QtCore.QObject):
    result_ready = QtCore.pyqtSignal(object)

    @QtCore.pyqtSlot(str)
    def do_work(self, myurl):
        cmd = "ffprobe -v quiet -print_format json -show_streams"
        args = shlex.split(cmd)

        args.append(myurl)

        ffprobeOutput = subprocess.check_output(args).decode("utf-8")
        ffprobeOutput = json.loads(ffprobeOutput)

        result = ffprobeOutput["streams"][0]

        self.result_ready.emit(result)


class MainProg(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainProg, self).__init__(parent)

        self.setFont(QtGui.QFont("Arial", 12))

        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)
        hlay = QtWidgets.QHBoxLayout(central_widget)

        left_widget = QtWidgets.QWidget()

        self.mediaPlayer = QtMultimedia.QMediaPlayer()
        self.video_widget = QtMultimediaWidgets.QVideoWidget()
        self.video_widget.setContentsMargins(30, 30, 30, 30)
        self.mediaPlayer.setVideoOutput(self.video_widget)

        self.sd_button = QtWidgets.QToolButton(text="SD", checkable=True)
        self.sd_button.setFixedSize(31, 32)
        self.code_lcd = QtWidgets.QLCDNumber()
        self.horizontal_lcd = QtWidgets.QLCDNumber()
        self.vertical_lcd = QtWidgets.QLCDNumber()
        self.display_aspect_ratio_lcd = QtWidgets.QLCDNumber()
        self.reference_lcd = QtWidgets.QLCDNumber()
        self.b_frames_lcd = QtWidgets.QLCDNumber()
        self.start_bits_lcd = QtWidgets.QLCDNumber()
        self.sample_aspect_ratio_lcd = QtWidgets.QLCDNumber()
        self.bit_rate_lcd = QtWidgets.QLCDNumber()
        self.tp1_button = QtWidgets.QToolButton(text="TP1")
        self.tp2_button = QtWidgets.QToolButton(text="TP2")
        self.led = QLed(self, onColour=QLed.Orange, shape=QLed.Circle)
        self.progressbar = QtWidgets.QProgressBar()

        for lcd in (
            self.code_lcd,
            self.horizontal_lcd,
            self.vertical_lcd,
            self.display_aspect_ratio_lcd,
            self.reference_lcd,
            self.b_frames_lcd,
            self.start_bits_lcd,
            self.sample_aspect_ratio_lcd,
            self.bit_rate_lcd,
        ):
            lcd.setFixedSize(146, 50)

        hlay.addWidget(left_widget)
        hlay.addWidget(self.video_widget, stretch=1)

        lay = QtWidgets.QGridLayout(left_widget)
        lay.setVerticalSpacing(5)

        for i, (text, widget) in enumerate(
            zip(
                (
                    "Video",
                    "Codec Name:",
                    "Horizontal:",
                    "Vertical:",
                    "Display Aspect Ratio:",
                    "Refrence:",
                    "B frames:",
                    "Start Bits:",
                    "Sample Aspect ratio:",
                    "Bit Rate:",
                ),
                (
                    self.sd_button,
                    self.code_lcd,
                    self.horizontal_lcd,
                    self.vertical_lcd,
                    self.display_aspect_ratio_lcd,
                    self.reference_lcd,
                    self.b_frames_lcd,
                    self.start_bits_lcd,
                    self.sample_aspect_ratio_lcd,
                    self.bit_rate_lcd,
                ),
            )
        ):
            label = QtWidgets.QLabel(text)
            lay.addWidget(label, i, 0)
            lay.addWidget(widget, i, 1, alignment=QtCore.Qt.AlignCenter)

        vlay = QtWidgets.QVBoxLayout()
        vlay.addWidget(self.tp1_button)
        vlay.addWidget(self.tp2_button)

        hlay2 = QtWidgets.QHBoxLayout()
        hlay2.addStretch(0)
        hlay2.addLayout(vlay)
        hlay2.addWidget(self.led)
        hlay2.addStretch(0)

        lay.addLayout(hlay2, lay.rowCount(), 0, 1, 2)
        lay.addWidget(self.progressbar, lay.rowCount(), 0, 1, 2)

        lay.setRowStretch(lay.rowCount(), 1)
        self.resize(960, 480)

        self.sd_button.toggled.connect(self.led.setValue)
        self.tp1_button.clicked.connect(self.on_tp_clicked)
        self.tp2_button.clicked.connect(self.on_tp_clicked)

        self.current_button = None

        thread = QtCore.QThread(self)
        thread.start()

        self.worker = Analyzer()
        self.worker.moveToThread(thread)
        self.worker.result_ready.connect(self.process_result)

    @QtCore.pyqtSlot()
    def on_tp_clicked(self):
        if self.sd_button.isChecked():
            urls_map = {
                self.tp1_button: "293.168.1.6:1115",
                self.tp2_button: "239.168.1.7:1116",
            }
            url = urls_map.get(self.sender(), "")
            if url:
                self.play(url)
                self.current_button = self.sender()
                self.current_button.setEnabled(False)

    def play(self, url):
        self.progressbar.setRange(0, 0)
        self.mediaPlayer.setMedia(QtMultimedia.QMediaContent(QtCore.QUrl(url)))
        self.mediaPlayer.play()
        wrapper = partial(self.worker.do_work, url)
        QtCore.QTimer.singleShot(0, wrapper)

    @QtCore.pyqtSlot(object)
    def process_result(self, result):
        self.current_button.setEnabled(True)
        self.current_button = None
        self.progressbar.setRange(0, 1)
        self.progressbar.setValue(0)

        for lcd, key in zip(
            (
                self.code_lcd,
                self.b_frames_lcd,
                self.horizontal_lcd,
                self.vertical_lcd,
                self.display_aspect_ratio_lcd,
                self.sample_aspect_ratio_lcd,
                self.reference_lcd,
            ),
            (
                "codec_name",
                "has_b_frames",
                "width",
                "height",
                "display_aspect_ratio",
                "sample_aspect_ratio",
                "refs",
            ),
        ):
            value = result.get(key, 0)
            lcd.display(value)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MainProg()
    w.show()
    sys.exit(app.exec_())

虽然我不认为需要使用线程,但在这种情况下使用QProcess更容易。

代码语言:javascript
复制
from functools import partial
import json
import shlex
import sys


from QLed import QLed

from PyQt5 import QtCore, QtGui, QtWidgets, QtMultimedia, QtMultimediaWidgets


class MainProg(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainProg, self).__init__(parent)

        self.setFont(QtGui.QFont("Arial", 12))

        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)
        hlay = QtWidgets.QHBoxLayout(central_widget)

        left_widget = QtWidgets.QWidget()

        self.mediaPlayer = QtMultimedia.QMediaPlayer()
        self.video_widget = QtMultimediaWidgets.QVideoWidget()
        self.video_widget.setContentsMargins(30, 30, 30, 30)
        self.mediaPlayer.setVideoOutput(self.video_widget)

        self.sd_button = QtWidgets.QToolButton(text="SD", checkable=True)
        self.sd_button.setFixedSize(31, 32)
        self.code_lcd = QtWidgets.QLCDNumber()
        self.horizontal_lcd = QtWidgets.QLCDNumber()
        self.vertical_lcd = QtWidgets.QLCDNumber()
        self.display_aspect_ratio_lcd = QtWidgets.QLCDNumber()
        self.reference_lcd = QtWidgets.QLCDNumber()
        self.b_frames_lcd = QtWidgets.QLCDNumber()
        self.start_bits_lcd = QtWidgets.QLCDNumber()
        self.sample_aspect_ratio_lcd = QtWidgets.QLCDNumber()
        self.bit_rate_lcd = QtWidgets.QLCDNumber()
        self.tp1_button = QtWidgets.QToolButton(text="TP1")
        self.tp2_button = QtWidgets.QToolButton(text="TP2")
        self.led = QLed(self, onColour=QLed.Orange, shape=QLed.Circle)
        self.progressbar = QtWidgets.QProgressBar()

        for lcd in (
            self.code_lcd,
            self.horizontal_lcd,
            self.vertical_lcd,
            self.display_aspect_ratio_lcd,
            self.reference_lcd,
            self.b_frames_lcd,
            self.start_bits_lcd,
            self.sample_aspect_ratio_lcd,
            self.bit_rate_lcd,
        ):
            lcd.setFixedSize(146, 50)

        hlay.addWidget(left_widget)
        hlay.addWidget(self.video_widget, stretch=1)

        lay = QtWidgets.QGridLayout(left_widget)
        lay.setVerticalSpacing(5)

        for i, (text, widget) in enumerate(
            zip(
                (
                    "Video",
                    "Codec Name:",
                    "Horizontal:",
                    "Vertical:",
                    "Display Aspect Ratio:",
                    "Refrence:",
                    "B frames:",
                    "Start Bits:",
                    "Sample Aspect ratio:",
                    "Bit Rate:",
                ),
                (
                    self.sd_button,
                    self.code_lcd,
                    self.horizontal_lcd,
                    self.vertical_lcd,
                    self.display_aspect_ratio_lcd,
                    self.reference_lcd,
                    self.b_frames_lcd,
                    self.start_bits_lcd,
                    self.sample_aspect_ratio_lcd,
                    self.bit_rate_lcd,
                ),
            )
        ):
            label = QtWidgets.QLabel(text)
            lay.addWidget(label, i, 0)
            lay.addWidget(widget, i, 1, alignment=QtCore.Qt.AlignCenter)

        vlay = QtWidgets.QVBoxLayout()
        vlay.addWidget(self.tp1_button)
        vlay.addWidget(self.tp2_button)

        hlay2 = QtWidgets.QHBoxLayout()
        hlay2.addStretch(0)
        hlay2.addLayout(vlay)
        hlay2.addWidget(self.led)
        hlay2.addStretch(0)

        lay.addLayout(hlay2, lay.rowCount(), 0, 1, 2)
        lay.addWidget(self.progressbar, lay.rowCount(), 0, 1, 2)

        lay.setRowStretch(lay.rowCount(), 1)
        self.resize(960, 480)

        self.sd_button.toggled.connect(self.led.setValue)
        self.tp1_button.clicked.connect(self.on_tp_clicked)
        self.tp2_button.clicked.connect(self.on_tp_clicked)

        self.current_button = None

        self.process = QtCore.QProcess(self)
        self.process.finished.connect(self.on_finish)

    @QtCore.pyqtSlot()
    def on_tp_clicked(self):
        if self.sd_button.isChecked():
            urls_map = {
                self.tp1_button: "293.168.1.6:1115",
                self.tp2_button: "239.168.1.7:1116",
            }
            url = urls_map.get(self.sender(), "")
            if url:
                self.play(url)
                self.current_button = self.sender()
                self.current_button.setEnabled(False)

    def play(self, url):
        self.progressbar.setRange(0, 0)
        self.mediaPlayer.setMedia(QtMultimedia.QMediaContent(QtCore.QUrl(url)))
        self.mediaPlayer.play()

        cmd = "ffprobe -v quiet -print_format json -show_streams"
        program, *args = shlex.split(cmd)
        args.append(url)
        self.process.start(program, args)

    @QtCore.pyqtSlot()
    def on_finish(self):
        data = self.process.readAllStandardOutput().data()
        if data:
            ffprobeOutput = json.loads(data)
            result = ffprobeOutput['streams'][0]
            for lcd, key in zip(
                (
                    self.code_lcd,
                    self.b_frames_lcd,
                    self.horizontal_lcd,
                    self.vertical_lcd,
                    self.display_aspect_ratio_lcd,
                    self.sample_aspect_ratio_lcd,
                    self.reference_lcd,
                ),
                (
                    "codec_name",
                    "has_b_frames",
                    "width",
                    "height",
                    "display_aspect_ratio",
                    "sample_aspect_ratio",
                    "refs",
                ),
            ):
                value = result.get(key, 0)
                lcd.display(value)


        self.current_button.setEnabled(True)
        self.current_button = None
        self.progressbar.setRange(0, 1)
        self.progressbar.setValue(0)



if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MainProg()
    w.show()
    sys.exit(app.exec_())
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59159254

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档