在子窗口小部件活动时阻止 QMainWindow ,pyqt
Posted
技术标签:
【中文标题】在子窗口小部件活动时阻止 QMainWindow ,pyqt【英文标题】:Block QMainWindow while child widget is alive , pyqt 【发布时间】:2014-03-14 16:26:28 【问题描述】:我希望当用户按下按钮时,在 MainWindow 被阻止等待表单填充后会出现一个表单
【问题讨论】:
问题标题中的“如何阻止”是什么意思? 窗体出现时主窗口无法访问 【参考方案1】:您无需执行其他答案建议的任何操作。使用任何exec()
方法是产生错误的可靠方法,因为突然之间您的gui 代码可以重新输入。不要这样做。
您需要做的就是在显示之前设置适当的窗口模式(这是重要的部分)。所以:
widget.setWindowModality(Qt.ApplicationModal)
widget.show()
如果您希望窗口仅阻止某个其他窗口,而不是整个应用程序:
widget.setWindowFlags(widget.windowFlags() | Qt.Window)
widget.setParent(otherWindow)
widget.setWindowModality(Qt.WindowModal)
widget.show()
请注意,此代码仅适用于 PyQt4,它不适用于 Qt 5,因为窗口功能属于与 QWidget 分开的类。
【讨论】:
@Vesanto 完全相同的代码在 PyQt5 上对我有用。另外(不是给你)阅读更多关于为什么不使用exec
的信息,请参阅Qt docs:doc.qt.io/qt-5/qdialog.html#exec,其中的一个示例错误是deleting the dialog's parent while the dialog is open via exec()
如何显示一个对话框只阻止一些窗口而不是整个应用程序?我试过你的代码widget.setWindowFlags(widget.windowFlags() | Qt.Window) widget.setParent(otherWindow) widget.setWindowModality(Qt.WindowModal) widget.show()
,但它确实有效?【参考方案2】:
您需要使用QDialog 并使用exec 显示它,这将阻止应用程序的其余部分,直到它关闭。 exec
的返回值还告诉您表单是否在未提交更改的情况下关闭(即取消)。
这是一个简单的演示脚本,展示了如何使用QDialog
:
from PyQt4 import QtCore, QtGui
class Dialog(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
self.checkbox1 = QtGui.QCheckBox('Option one', self)
self.checkbox2 = QtGui.QCheckBox('Option two', self)
self.buttonOk = QtGui.QPushButton('Ok', self)
self.buttonOk.clicked.connect(self.accept)
self.buttonCancel = QtGui.QPushButton('Cancel', self)
self.buttonCancel.clicked.connect(self.reject)
layout = QtGui.QGridLayout(self)
layout.addWidget(self.checkbox1, 0, 0, 1, 2)
layout.addWidget(self.checkbox2, 1, 0, 1, 2)
layout.addWidget(self.buttonOk, 2, 0)
layout.addWidget(self.buttonCancel, 2, 1)
class Window(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
widget = QtGui.QWidget(self)
layout = QtGui.QVBoxLayout(widget)
self.button = QtGui.QPushButton('Show Dialog', self)
self.button.clicked.connect(self.handleButton)
layout.addWidget(self.button)
self.setCentralWidget(widget)
def handleButton(self):
dialog = Dialog(self)
if dialog.exec_() == QtGui.QDialog.Accepted:
print('Option one: %s' % dialog.checkbox1.isChecked())
print('Option two: %s' % dialog.checkbox2.isChecked())
else:
print('Cancelled')
dialog.deleteLater()
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 300, 200, 100)
window.show()
sys.exit(app.exec_())
【讨论】:
【参考方案3】:这是你需要的
self.setWindowModality(QtCore.Qt.ApplicationModal)
【讨论】:
您缺少“被阻止的待处理表单填写”部分。询问的行为是对话框的 exec_() 之一。【参考方案4】:好的,所以你想阻止父窗口,直到子窗口关闭。
dialog = QInputDialog()
dialog.exec_()
使用exec_()函数,它会一直阻塞,直到子窗口没有关闭
更多信息:
launch a PyQT window from a main PyQt window, and get the user input?
Python - make a window appear on top of another, block access to other windows until button clicked
【讨论】:
thnx,但我想放一个小部件(子窗口)而不是 QInputDialog【参考方案5】:使用表单子类化 QDialog 或 QWidget,然后在主窗口的构造函数中像这样连接它。您需要将此代码从 c++ 转换为 python:
QObject::connect(myPushButton, SIGNAL(clicked), this, SLOT(on_myPushButton()));
//...
void MainWindow::on_myPushButton()
Dialog d;
int retVal = d.exec();// this is a blocking call
// Here the user has finished filling out the form.
// save any data that should be in the form, or respond to the retVal
编辑:添加了使用 QDialog::exec()
的文档链接
http://qt-project.org/doc/qt-5/qdialog.html#exec
希望对您有所帮助。
【讨论】:
我想放一个小部件(子窗口)而不是 QInputDialog :/ 要获得阻止功能,您应该使用QDialog
。它是QWidget
的子类,几乎可以在任何方面像QWidget
一样使用。 QInputDialog
和 QMessageBox
及其静态方法是 QDialog
的有用子类,但不是唯一的。
exec()
调用创建了一个事件循环,并让小部件的 GUI 在该循环中运行,使其保持响应。您可以在源代码中看到,它创建了一个事件循环并运行它exec()
并等待该循环。 qt.gitorious.org/qt/qt/source/…【参考方案6】:
必须创建Widget继承自Qdialog
AjoutArBase, AjoutArForm = uic.loadUiType('ajoutArticle.ui')
class AjoutArticle(AjoutArBase,QtGui.QDialog):
【讨论】:
以上是关于在子窗口小部件活动时阻止 QMainWindow ,pyqt的主要内容,如果未能解决你的问题,请参考以下文章