python - 在线程中的 Qdialog 上调用 exec() 效果不佳

标签 python pyqt pyqt5 python-3.7

我想在线程中调用 my_dialog.exec(),但是当主窗口(意思是主线程)处理事件时它工作得很糟糕,我想知道如何处理这个问题

这是我的测试程序:

import sys
from PyQt5.Qt import *
from threading import Thread
from time import sleep

class Main(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setGeometry(500, 500, 500, 200)

        self.dialog = QDialog(self)
        self.dialog.setGeometry(500, 500, 200, 100)

        btn = QPushButton('click', self)
        btn.clicked.connect(self.show_dialog)

        self.show()

    def show_dialog(self):
        Thread(target=self.execute).start()

    def execute(self):
        sleep(2)
        # keep moving mainwindow untill dialog have shown
        self.dialog.exec_()

app = QApplication(sys.argv)
e = Main()
sys.exit(app.exec_())

当我按下按钮时,它会先休眠两秒钟。 当主窗口没有事件时,这是正常的。 但是当我在两个 sleep 秒内继续移动主窗口(或其他事件,例如调整大小)时,它们都将变得无响应

最佳答案

不,您不能从另一个线程修改 GUI,请使用信号。

TL;DR;

我在 Qt 中分享了一条黄金法则:你不能也不应该从另一个线程修改 GUI。欲了解更多信息,请阅读:GUI Thread and Worker Thread .

考虑到上述情况,Qt 中不同线程中的元素之间进行交互的自然方式是使用信号,因为它们是 thread-safe如下所示:

class Main(QMainWindow):
    <b>customSignal = pyqtSignal()</b>

    def __init__(self):
        # ...

        self.show()
        <b>self.customSignal.connect(self.dialog.exec_)</b>

    def show_dialog(self):
        Thread(target=self.execute).start()

    def execute(self):
        sleep(2)
        # keep moving mainwindow untill dialog have shown
        <b>self.customSignal.emit()</b>

关于python - 在线程中的 Qdialog 上调用 exec() 效果不佳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58229629/

相关文章:

python - 如何在 matplotlib 小部件的嵌入式图形上使用跨度选择器?

python - 将 x 轴刻度更改为自定义字符串

python - 在 heroku chromedriver buildpack 上不支持 chrome buildpack

python - 使用 Python Selenium 下载 zip 文件

python - 将具有不匹配键的字典列表转储到 csv 文件中

python - 将复选框动态插入到 tabWidget 中

python - 防止 okay QPushButton 在按回车时接受对话框

python - 将函数与 Python(sympy、quad)集成,其中结果是我想要绘制的另一个函数

python - QLineEdit 使用按钮显示从鼠标选择中选择的文本

python - 如何更改工具栏的默认位置?