【问题标题】:QMessageBox in other thread其他线程中的 QMessageBox
【发布时间】:2021-12-02 11:10:26
【问题描述】:
import time
import sys, threading
from PyQt4 import QtGui, QtCore
from PyQt4.QtGui import QApplication


class Global:
    def __init__(self):
        for c in MyClass, MainWindow:
            cl = c()
            setattr(self, c.__name__, cl)
            setattr(cl, 'global_', self)


class MyClass:
    def work(self):
        for r in range(100):
            if r == 2:
                self.global_.MainWindow.SignalBox.emit('MyClass NO PAUSE')  # need pause !!!
            else:
                print(r)
            time.sleep(1)


class MainWindow(QtGui.QWidget):
    Signal = QtCore.pyqtSignal(str)
    SignalBox = QtCore.pyqtSignal(str)

    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.resize(300, 300)

        self.lab = QtGui.QLabel()
        lay = QtGui.QGridLayout()
        lay.addWidget(self.lab)
        self.setLayout(lay)

        self.msgBox = lambda txt: getattr(QtGui.QMessageBox(), 'information')(self, txt, txt)
        self.Signal.connect(self.lab.setText)
        self.SignalBox.connect(self.msgBox)

    def thread_no_wait(self):
        self.global_.MainWindow.SignalBox.emit('MyClass PAUSE OK')
        threading.Thread(target=self.global_.MyClass.work).start()

    def thread_main(self):
        def my_work():
            for r in range(100):
                self.Signal.emit(str(r))
                time.sleep(1)
        threading.Thread(target=my_work).start()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    g = Global()
    g.MainWindow.show()
    g.MainWindow.thread_main()
    g.MainWindow.thread_no_wait()
    app.exec_()

如何从另一个进程运行 QMessageBox?

MyClass.work 在单独的线程中执行而没有加入是必要的 MyClass 如果它导致 QMessageBox 挂起如果我们定义 QMessageBox 是 MainWindow ,则会调用错误

QObject::startTimer: 定时器不能从另一个线程启动 QApplication:对象事件过滤器不能在不同的线程中。 并且在这个调用QMessageBox中调用了一个单独的线程,并且工作没有暂停

【问题讨论】:

  • 我不明白你在问什么,但是除了主线程之外,不可能在线程中运行任何 GUI 代码。

标签: python pyqt


【解决方案1】:

听起来您想暂停线程的执行,直到主线程中的某些操作完成。有几种方法可以做到这一点。一种简单的方法是使用共享全局变量。

PAUSE = False

class MyClass:
    def work(self):
        global PAUSE
        for r in range(100):
            while PAUSE:
                time.sleep(1)
            if r == 2:
                self.global_.MainWindow.SignalBox.emit('MyClass NO PAUSE')
                PAUSE = True
            ...

class MainWindow(...)

    def msgBox(self, txt):
        QtGui.QMessageBox.information(self, txt, txt)
        global PAUSE
        PAUSE = False

如果您使用 QThreads 而不是 python 线程,您实际上可以在另一个线程中调用函数并阻塞,直到该函数使用 QMetaObject.invokeMethod 完成

@QtCore.pyqtSlot(str)
def msgBox(self, txt):
    ...

...

if r == 2:
    # This call will block until msgBox() returns
    QMetaObject.invokeMethod(
        self.global_.MainWindow, 
        'msgBox', 
        QtCore.Qt.BlockingQueuedConnection, 
        QtCore.Q_ARG(str, 'Text to msgBox')
    )

【讨论】:

  • 谢谢,这正是我想要的
猜你喜欢
  • 2012-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-27
  • 1970-01-01
  • 2017-02-28
  • 1970-01-01
相关资源
最近更新 更多