什么是 PyQt 等价于 WinForms 激活事件?
Posted
技术标签:
【中文标题】什么是 PyQt 等价于 WinForms 激活事件?【英文标题】:What is the PyQt Equivalent to WinForms Activated Event? 【发布时间】:2019-12-30 17:43:39 【问题描述】:我正在编写一个小型 PyQt 应用程序,它需要在应用程序启动之前运行一些检查,如果任何检查失败,应用程序需要通知用户它无法运行然后退出。
在 WinForms 中。我可以简单地做到这一点:
var form = new Form();
form.Activated += (s, e) =>
var condition = true;
if (condition)
MessageBox.Show("oh dear, something's wrong.");
Application.Exit();
;
当主应用程序窗口加载时,PyQt 似乎没有可以连接的信号,并且当条件失败时我当前的尝试甚至没有触发对话框。
这是我目前拥有的(MRE(。程序流程如下:
import sys
import winreg
from PyQt5.QtWidgets import QApplication, QWidget, QMessageBox
class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
def loadData(self):
try:
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\Path\To\Nonexistant\Key')
x = winreg.QueryValueEx(key, 'some_key')[0]
print(x)
except FileNotFoundError:
error = QMessageBox()
error.setIcon(QMessageBox.Critical)
error.setText('Cannot locate installation directory.')
error.setWindowTitle('Cannot find registry key')
error.setStandardButtons(QMessageBox.Ok)
error.show()
QApplication.quit()
def main():
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
main_window.loadData()
sys.exit(app.exec_())
main()
我的最终目标是让loadData()
在应用程序完全加载并显示给用户时运行。
更新:程序现在按预期运行。我不得不:
将error.show()
更改为error.exec_()
将QApplication.quit()
更改为sys.exit()
在main_window.show()
之后致电main_window.loadData()
【问题讨论】:
据我了解(我不知道 winforms),您希望应用程序在用户单击 QMessageBox 上的 OK 后结束,对吗? 没错。一旦应用程序加载,我需要它来执行检查,如果它失败,显示 QMessageBox 然后退出。我现在根本无法显示 QMessageBox。 【参考方案1】:show 方法没有阻塞,所以一旦执行,QMessageBox 就会显示在QApplication.quit()
,而你应该使用exec_()
,它会等到用户通过按钮关闭QMessageBox。
# ...
error.setStandardButtons(QMessageBox.Ok)
# error.show()
error.exec_()
QApplication.quit()
更新:
另一方面,QApplication.quit() 在 eventloop 尚未启动时无法使用,因此这种情况下的解决方案是稍后使用 QTimer.singleShot() 删除应用程序:
class MainWindow(QWidget):
# UI stuff omitted...
def loadData(self):
try:
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\Path\To\Key')
path = winreg.QueryValueEx(key, 'install_path')[0]
# I'll do stuff with path here...
except FileNotFoundError:
error = QMessageBox()
error.setIcon(QMessageBox.Critical)
error.setText('Cannot locate directory.')
error.setWindowTitle('Cannot find registry key')
error.setStandardButtons(QMessageBox.Ok)
error.exec_()
QTimer.singleShot(0, QApplication.quit)
def main():
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
main_window.loadData()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
另外一个等价的代码如下
class MainWindow(QWidget):
# UI stuff omitted...
def loadData(self):
try:
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\Path\To\Key')
path = winreg.QueryValueEx(key, 'install_path')[0]
# I'll do stuff with path here...
except FileNotFoundError:
error = QMessageBox()
error.setIcon(QMessageBox.Critical)
error.setText('Cannot locate directory.')
error.setWindowTitle('Cannot find registry key')
error.setStandardButtons(QMessageBox.Ok)
error.exec_()
QApplication.quit()
def main():
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
QTimer.singleShot(0, main_window.loadData)
sys.exit(app.exec_())
if __name__ == '__main__':
main()
【讨论】:
好的,问题解决了一半,但是点击确定后,应用程序仍在加载中。我该如何解决? @Jake 我建议你添加一个版本,并且不要覆盖代码,因为如果你这样做了,那么我的回答将毫无意义。另一方面,您必须提供minimal reproducible example,因为可能存在问题,但不幸的是我们不知道。 这很奏效,第二个例子对我来说更像是“winforms”。 @eyllanesc 因为即使应用程序未启动也可以执行 QMessageBox,如果loadData
成功并在这种情况下执行应用程序,是否应该返回 True 更好?
@musicamante OP 希望首先显示窗口(而不是 QMessageBox),此外 OP 似乎有一个我不想更改的项目结构,但它也是一个有效的选项。 以上是关于什么是 PyQt 等价于 WinForms 激活事件?的主要内容,如果未能解决你的问题,请参考以下文章
pyQT slot decorator 啥是 C++ 等价物
PyQt_PyObject在使用新式信号/插槽时是等价的吗?
pyqt5 如何识别该函数中是哪个qpush_button激活了该函数? [关闭]
什么是'import * as ...'等价于require?