简体   繁体   English

PySide2 非阻塞 QMessageBox 不显示文本

[英]PySide2 Non-Blocking QMessageBox doesn't show text

While my application does some time-consuming stuff, I want to display a message box to the user while the applications is busy.虽然我的应用程序做了一些耗时的事情,但我想在应用程序繁忙时向用户显示一个消息框。 I don't want any buttons (like OK or Cancel ) and I can't call exec_() on the message box because that is blocking.我不想要任何按钮(如OKCancel ),而且我无法在消息框上调用exec_() ,因为那是阻塞的。

I checked a number of qt sites and the code I need seems to boil down to:我检查了一些qt站点,我需要的代码似乎可以归结为:

    message_box = QMessageBox()
    message_box.setText(str('Reading Device, Please Wait...'))
    message_box.show()
    # do work here
    message_box.close()

When I run the code, I get the message box, but without the text.当我运行代码时,我得到了消息框,但没有文本。 What am I doing wrong?我究竟做错了什么?

I've included a working example below:我在下面包含了一个工作示例:

#!/usr/bin/env python3

import sys
import time
from PySide2.QtWidgets import (QLineEdit, QPushButton, QApplication,
    QVBoxLayout, QDialog, QMessageBox)

class Form(QDialog):

    def __init__(self, parent=None):
        super(Form, self).__init__(parent)
        self.button = QPushButton("Click Me")
        layout = QVBoxLayout()
        layout.addWidget(self.button)
        self.setLayout(layout)
        # Add button signal to dowork slot
        self.button.clicked.connect(self.dowork)

    def dowork(self):
        message_box = QMessageBox()
        message_box.setText(str('Reading Device, Please Wait...'))
        message_box.show()
        delay = 2.5
        while delay:
           sys.stdout.write('Working...\n')
           time.sleep(0.5)  # do some time-consuming stuff...
           delay -= 0.5
        message_box.close()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    form = Form()
    print('starting app...')
    form.show()
    sys.exit(app.exec_())

If you click the button, the message box pops up and is shown while the 'work' is being done.如果单击该按钮,消息框会弹出并在“工作”完成时显示。 When the 'work' is finished, the message box disappears again - as it should.当“工作”完成时,消息框再次消失 - 应该如此。 But no text is shown in the message box.但是消息框中没有显示任何文本。

There is a similar question here: qmessagebox-not-show-text-when-call-show , but that does not answer my question.这里有一个类似的问题: qmessagebox-not-show-text-when-call-show ,但这并没有回答我的问题。

You can not have a task that consumes a lot of time (more than 30 ms) since it blocks the GUI eventloop preventing Qt from doing its job normally, instead it uses a thread next to the signals to update the GUI from the other thread:您不能有一个消耗大量时间(超过 30 毫秒)的任务,因为它会阻止 GUI 事件循环,从而阻止 Qt 正常工作,而是使用信号旁边的线程从另一个线程更新 GUI:

import sys
import threading
import time
from PySide2 import QtCore, QtWidgets

class Form(QtWidgets.QDialog):
    started = QtCore.Signal()
    finished = QtCore.Signal()

    def __init__(self, parent=None):
        super(Form, self).__init__(parent)
        self.button = QtWidgets.QPushButton("Click Me")
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.button)
        # Add button signal to dowork slot
        self.button.clicked.connect(self.on_clicled)

        self._message_box = QtWidgets.QMessageBox()
        self._message_box.setText(str('Reading Device, Please Wait...'))
        self._message_box.setStandardButtons(QtWidgets.QMessageBox.NoButton)
        self.started.connect(self._message_box.show)
        self.finished.connect(self._message_box.accept)

    @QtCore.Slot()
    def on_clicled(self):
        thread = threading.Thread(target=self.dowork, daemon=True)
        thread.start()

    def dowork(self):
        delay = 2.5
        self.started.emit()
        while delay:
           sys.stdout.write('Working...\n')
           time.sleep(0.5)  # do some time-consuming stuff...
           delay -= 0.5
        self.finished.emit()

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    form = Form()
    print('starting app...')
    form.show()
    sys.exit(app.exec_())

You should almost certainly be using QProgressDialog.您几乎肯定应该使用 QProgressDialog。 Set minimum and maximum to zero for an 'indeterminate' look.将最小值和最大值设置为零以获得“不确定”外观。

https://doc.qt.io/qt-5/qprogressdialog.html https://doc.qt.io/qt-5/qprogressdialog.html

Although forcing a redraw after your setText() will probably work:尽管在setText()之后强制重绘可能会起作用:

self._message_box.repaint()
QtWidgets.QApplication.processEvents()

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

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