【问题标题】:What is the proper way to do this using pyqt?使用 pyqt 执行此操作的正确方法是什么?
【发布时间】:2014-09-26 23:05:00
【问题描述】:

下面的代码给出了一个错误消息: “QObject::startTimer:定时器不能从另一个线程启动。” 我真的不明白为什么。主要是因为我几乎得到了这个线程问题以及信号和插槽机制。如何将“int(percent)”变量传递给对话框或主 GUI 的对话框以实时刷新进度条对象?

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
import urllib.request

class Main(QWidget):
    def __init__(self, parent = None):
        super(Main, self).__init__()
        self.label = QLabel("TheMainGUI")
        self.pushbutton = QPushButton("Download")

        layout = QHBoxLayout()
        layout.addWidget(self.label)
        layout.addWidget(self.pushbutton)
        self.setLayout(layout)

        self.pushbutton.clicked.connect(self.download)

    def download(self):
        self.filedownloadthread = FileDownloadThread()
        self.filedownloadthread.start()

class Dialog(QDialog):
    def __init__(self, parent = None):
        super(Dialog, self).__init__()
        self.progbar = QProgressBar()
        layout = QVBoxLayout()
        layout.addWidget(self.progbar)
        self.setLayout(layout)

class FileDownloadThread(QThread):
    def __init__(self):
        super(FileDownloadThread, self).__init__()
        self.dialog = Dialog()
        self.dialog.show()

    def run(self):
        url = "http://mysource.net//myfile"
        outputfile = "d://file//path//etc//myfile"

        def reporthook(blocknum, blocksize, totalsize):
            readsofar = blocknum * blocksize
            if totalsize > 0:
                percent = readsofar * 1e2 / totalsize

                self.dialog.progbar.setValue(int(percent))
                s = "\r%5.1f%% %*d / %d" % (
                    percent, len(str(totalsize)), readsofar, totalsize)
                sys.stderr.write(s)
                if readsofar >= totalsize:
                    sys.stderr.write("\n")
            else:
                sys.stderr.write("read %d\n" % (readsofar,))

        proxy = urllib.request.ProxyHandler({'http': "myproxy"})
        opener = urllib.request.build_opener(proxy)
        urllib.request.install_opener(opener)
        urllib.request.urlretrieve(url, outputfile, reporthook)

app = QApplication(sys.argv)
form = Main()
form.show()
app.exec_()

【问题讨论】:

  • 您不能在主线程之外创建或操作 GUI 元素。您应该在FileDownloadThread 之外(例如在Main 内部)实例化Dialog,并从FileDownloadThread 向其发送信号以更新进度条。
  • 我更新了代码。是这样吗?
  • 您的想法似乎是正确的。它现在有效吗?我对您使用的旧式信号和插槽机制不太熟悉,所以我无法评论它是否正确。此外,请尽量不要使用使代码与您的原始问题不一致的更新来修改您的原始帖子,因为它只会使其他人感到困惑。最好在原始帖子的末尾添加更新
  • 看看这篇文章:pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html 我建议你切换到 PyQt 的“新”风格的信号/槽机制。
  • @user3419537 我建议您将评论移至答案

标签: python multithreading pyqt pyqt4 qprogressbar


【解决方案1】:

使用旧的信号和槽机制可以正常工作。

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
import urllib.request

class Main(QWidget):
    def __init__(self, parent = None):
        super(Main, self).__init__()
        self.label = QLabel("TheMainGUI")
        self.pushbutton = QPushButton("Download")

        layout = QHBoxLayout()
        layout.addWidget(self.label)
        layout.addWidget(self.pushbutton)
        self.setLayout(layout)

        self.pushbutton.clicked.connect(self.download)

    def download(self):
        self.dialog = Dialog()
        self.dialog.show()

class Dialog(QDialog):
    def __init__(self, parent = None):
        super(Dialog, self).__init__()
        self.progbar = QProgressBar()
        layout = QVBoxLayout()
        layout.addWidget(self.progbar)
        self.setLayout(layout)

        self.filedownloadthread = FileDownloadThread()
        self.connect(self.filedownloadthread, SIGNAL('signal'), self.update)
        self.filedownloadthread.start()

    def update(self, percent):
        self.progbar.setValue(percent)

class FileDownloadThread(QThread):
    def __init__(self):
        super(FileDownloadThread, self).__init__()

    def run(self):
        url = "http://mysource.net//myfile"
        outputfile = "d://file//path//etc//myfile"

        def reporthook(blocknum, blocksize, totalsize):
            readsofar = blocknum * blocksize
            if totalsize > 0:
                percent = readsofar * 1e2 / totalsize

                self.dialog.progbar.setValue(int(percent))
                s = "\r%5.1f%% %*d / %d" % (
                    percent, len(str(totalsize)), readsofar, totalsize)
                sys.stderr.write(s)
                if readsofar >= totalsize:
                    sys.stderr.write("\n")
            else:
                sys.stderr.write("read %d\n" % (readsofar,))
            self.emit(SIGNAL('signal'), int(percent))

        proxy = urllib.request.ProxyHandler({'http': "myproxy"})
        opener = urllib.request.build_opener(proxy)
        urllib.request.install_opener(opener)
        urllib.request.urlretrieve(url, outputfile, reporthook)

app = QApplication(sys.argv)
form = Main()
form.show()
app.exec_()

【讨论】:

    猜你喜欢
    • 2021-08-23
    • 2016-02-11
    • 1970-01-01
    • 1970-01-01
    • 2012-10-15
    • 1970-01-01
    • 2012-10-02
    • 2014-01-06
    • 1970-01-01
    相关资源
    最近更新 更多