首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么QMessageBox.exec()没有阻塞我的线程

为什么QMessageBox.exec()没有阻塞我的线程
EN

Stack Overflow用户
提问于 2021-11-09 08:25:45
回答 1查看 57关注 0票数 0

请查看我的应用程序中的以下代码片段:

代码语言:javascript
运行
复制
requestDialogSignal = QtCore.pyqtSignal()

class MainWindow(QMainWindow):
   def __init__(self):
   ...
   self.requestDialogSignal.connect(self.slotRequestDialog, Qt.QueuedConnection)

def slotRequestDialog():
   mbox = QtWidgets.QMessageBox(QtWidgets.QMessageBox.NoIcon, "title", "message")
   mbox.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
   result = mbox.exec()      

def CreateDialogs(self):
   self.requestDialogSignal.emit()
   time.sleep(1)
   self.requestDialogSignal.emit()

app = QApplication(sys.argv)
window = MainWindow()
window.show()

t = threading.Thread(target=window.CreateDialogs)
t.start()

app.exec()

本质上,我试图实现的是第二个QMessageBox只有在第一个得到回答后才会出现。我期望第一个QMessageBox阻塞exec()上的接收器线程,这是因为Qt.QueuedConnection不允许第二次调用该插槽。如果我将连接更改为Qt.BlockingQueuedConnection,它会按预期运行,尽管这会阻塞发送线程,这不是我想要的。

EN

Stack Overflow用户

发布于 2021-11-09 10:59:24

试试这样的东西。我没有测试它,因为我的机器上既没有PyQt也没有PySide。可能会有一些小问题,但逻辑是清晰的,我希望可以理解。

代码语言:javascript
运行
复制
requestDialogSignal = QtCore.pyqtSignal()

class MainWindow(QMainWindow):
   def __init__(self):
      self.state = 0 # a state variable which can be used to define the dialog opening logic
      ...

   def openDialog(self):
      mbox = QtWidgets.QMessageBox(QtWidgets.QMessageBox.NoIcon, "title", "message", self) # use self to give the dialog a parent; not strictly needed but it is a good practice
      mbox.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
      mbox.finished.connect(self.onDialogFinished) # or you can connect to accepted or rejected signals to finetune the logic
      mbox.open() # open() makes the dialog window-modal but does not block the code

   def onDialogFinished(self):
      self.state += 1
      if self.state == 1: # makes sure we open te dialog only twice, but you can change the logic as you like with the state variable
         self.openDialog()

app = QApplication(sys.argv)
window = MainWindow()
window.show()
window.openDialog()

app.exec()

我相信下面的解决方案也应该是可行的,但它是丑陋的,原因有三。1)在应用程序的exec()之前调用对话框的exec()。2)使用过多的exec(),这不是一个好的做法。如果可能的话,应该避免使用exec()。3)包含不必要的递归...我认为这三种反对意见没有一个是错的,它们只是丑陋,我不喜欢它们。

代码语言:javascript
运行
复制
requestDialogSignal = QtCore.pyqtSignal()

class MainWindow(QMainWindow):
   def __init__(self):
      self.state = 0 # a state variable which can be used to define the dialog opening logic
      ...

   def execDialog(self):
      mbox = QtWidgets.QMessageBox(QtWidgets.QMessageBox.NoIcon, "title", "message", self)
      mbox.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
      mbox.exec() # blocks the code until closed
      self.state += 1
      if self.state == 1: # makes sure we open te dialog only twice, but you can change the logic as you like with the state variable
         self.execDialog()

app = QApplication(sys.argv)
window = MainWindow()
window.show()
window.execDialog()

app.exec()

我觉得你的代码奇怪的是,你把同一个对话框显示了两次。这真的是你想要的吗?我猜你实际上想要显示两个不同的对话框。在这种情况下,代码看起来会不同。但不管怎样,我已经向您展示了如何避免线程以及如何正确使用(或避免) exec()。我非常赞成使用我的第一个例子,而不是第二个。

票数 0
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69894885

复制
相关文章

相似问题

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