从按钮单击 Pyside2 触发消息框关闭整个应用程序
Pyside2 trigger messagebox from button click closes whole application
我想在不关闭整个应用程序的情况下通过单击按钮触发 messagebox
,我在之前的项目中设法做到了这一点,但这次的行为确实出乎意料。当我点击 ok
或 messagebox
上的叉号时,应用程序也没有任何错误地关闭。这是最小的例子
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.set_and_load_ui()
def set_and_load_ui(self):
self.ui = QUiLoader().load('main.ui', self)
def trigger_messagebox(self):
self.messagebox()
def messagebox(self,x=""):
msg = QMessageBox(self)
msg.setIcon(QMessageBox.Information)
msg.setText("{}".format(x))
msg.setInformativeText("test")
msg.setWindowTitle("test")
msg.exec_()
app = QtWidgets.QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.ui.show()
# mainWindow.trigger_messagebox() #this is fine
mainWindow.ui.mainmenuButton.clicked.connect(lambda: mainWindow.trigger_messagebox()) #this is not fine
exit_code = (app.exec_())
只是为了检查一下,如果消息框本身导致了问题,我尝试直接在我的代码中调用它,但结果很好,但当我尝试通过单击按钮触发它时却不行
问题与 QUiLoader 使用给定的父对象作为参数加载 UI 这一事实有关,并且由于 UI 已经是 QMainWindow,您实际上是在将 QMainWindow 加载到另一个,不受支持:QMainWindows 是非常特殊的 QWidget 类型,旨在用作 顶级小部件。
我不清楚 技术 静默 quit 的原因,但这肯定与加载的 window 实际上有父项(MainWindow
实例),即使未显示该父项(因为您显示的是 ui
)。
不幸的是,与 PyQt 不同(通过 uic.loadUi
函数),PySide 不提供将 UI 文件“安装”到现有实例的方法,因此如果您想继续使用PySide只有两个选项:
不要在 Designer 中使用主 window,而是使用普通小部件(Designer 的“新建表单”对话框中的“小部件”),使用 QUiLoader
加载它并使用 setCentralWidget()
(这是 强制性 ,因为,正如文档也 notes,“不支持创建没有中央小部件的主要 window "):
self.ui = QUiLoader().load('main.ui', self)
self.setCentralWidget(self.ui)
这种方法的缺点是您无法再使用 Designer 中的主要 window 功能(因此,没有菜单、状态栏、停靠小部件或工具栏)。
使用pyside-uic生成python代码,并使用多重继承方式“安装”;以下假设您将 ui 文件导出为 mainWindow.py
:
from mainWindow import ui_mainWindow
class MainWindow(QtWidgets.QMainWindow, ui_mainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)
# no "set_and_load_ui"
self.mainmenuButton.clicked.connect(self.trigger_messagebox)
# ...
app = QtWidgets.QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
exit_code = (app.exec_())
如您所见,现在您可以直接访问小部件(没有 ui
对象)。这种方法的缺点是您必须记住每次修改相关的 ui.
时 总是 生成 python 文件
我想在不关闭整个应用程序的情况下通过单击按钮触发 messagebox
,我在之前的项目中设法做到了这一点,但这次的行为确实出乎意料。当我点击 ok
或 messagebox
上的叉号时,应用程序也没有任何错误地关闭。这是最小的例子
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.set_and_load_ui()
def set_and_load_ui(self):
self.ui = QUiLoader().load('main.ui', self)
def trigger_messagebox(self):
self.messagebox()
def messagebox(self,x=""):
msg = QMessageBox(self)
msg.setIcon(QMessageBox.Information)
msg.setText("{}".format(x))
msg.setInformativeText("test")
msg.setWindowTitle("test")
msg.exec_()
app = QtWidgets.QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.ui.show()
# mainWindow.trigger_messagebox() #this is fine
mainWindow.ui.mainmenuButton.clicked.connect(lambda: mainWindow.trigger_messagebox()) #this is not fine
exit_code = (app.exec_())
只是为了检查一下,如果消息框本身导致了问题,我尝试直接在我的代码中调用它,但结果很好,但当我尝试通过单击按钮触发它时却不行
问题与 QUiLoader 使用给定的父对象作为参数加载 UI 这一事实有关,并且由于 UI 已经是 QMainWindow,您实际上是在将 QMainWindow 加载到另一个,不受支持:QMainWindows 是非常特殊的 QWidget 类型,旨在用作 顶级小部件。
我不清楚 技术 静默 quit 的原因,但这肯定与加载的 window 实际上有父项(MainWindow
实例),即使未显示该父项(因为您显示的是 ui
)。
不幸的是,与 PyQt 不同(通过 uic.loadUi
函数),PySide 不提供将 UI 文件“安装”到现有实例的方法,因此如果您想继续使用PySide只有两个选项:
不要在 Designer 中使用主 window,而是使用普通小部件(Designer 的“新建表单”对话框中的“小部件”),使用
QUiLoader
加载它并使用setCentralWidget()
(这是 强制性 ,因为,正如文档也 notes,“不支持创建没有中央小部件的主要 window "):self.ui = QUiLoader().load('main.ui', self) self.setCentralWidget(self.ui)
这种方法的缺点是您无法再使用 Designer 中的主要 window 功能(因此,没有菜单、状态栏、停靠小部件或工具栏)。
使用pyside-uic生成python代码,并使用多重继承方式“安装”;以下假设您将 ui 文件导出为
mainWindow.py
:from mainWindow import ui_mainWindow class MainWindow(QtWidgets.QMainWindow, ui_mainWindow): def __init__(self): super(MainWindow, self).__init__() self.setupUi(self) # no "set_and_load_ui" self.mainmenuButton.clicked.connect(self.trigger_messagebox) # ... app = QtWidgets.QApplication(sys.argv) mainWindow = MainWindow() mainWindow.show() exit_code = (app.exec_())
如您所见,现在您可以直接访问小部件(没有
时 总是 生成 python 文件ui
对象)。这种方法的缺点是您必须记住每次修改相关的 ui.