在 spyder 中从一个提示符运行 pyqt 应用程序两次
Posted
技术标签:
【中文标题】在 spyder 中从一个提示符运行 pyqt 应用程序两次【英文标题】:Running a pyqt application twice from one prompt in spyder 【发布时间】:2013-10-18 21:26:37 【问题描述】:我在spyder
中运行pyqt4
应用程序,然后以QtGui.QMainWindow.close()
退出,它返回到spyder python interpreter
提示符。但是,如果我再次尝试运行该应用程序runfile('C:/Python33/~/qtapp.py', wdir=r'C:/Python33/~/Appdir')
窗口不会显示。我必须关闭 python 解释器窗口并打开一个新窗口,然后才能再次运行我的 pyqt4
应用程序。这表明我是。
-
未正确关闭应用程序
应用程序运行不正确
我希望能够在同一提示下运行 pyqt4
应用程序,这将加快我的开发时间
示例代码如下:
from PyQt4 import QtCore, QtGui, Qwt5
import sys
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(200, 200)
self.checkBox = QtGui.QCheckBox(MainWindow)
self.checkBox.setGeometry(QtCore.QRect(100, 100, 70, 17))
self.checkBox.setObjectName("checkBox")
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "Dialog",None, QtGui.QApplication.UnicodeUTF8))
self.checkBox.setText(QtGui.QApplication.translate("MainWindow", "CheckBox", None, QtGui.QApplication.UnicodeUTF8))
class MainWindow(QtGui.QMainWindow,Ui_MainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)
app = QtGui.QApplication(sys.argv)
form = MainWindow()
form.show()
app.exec_()
在窗口出现后运行它,再次运行后窗口不显示, 这是我的版本信息:
Python 3.3.2 (v3.3.2:d047928ae3f6, May 16 2013, 00:03:43) [MSC v.1600 32 bit (Intel)] on win32 输入“help”、“copyright”、“credits”或“license”了解更多信息。
导入 NumPy 1.7.1、SciPy 0.12.0、Matplotlib 1.3.0 + guidata 1.6.1、guiqwt 2.3.1 输入“科学”了解更多详情。
【问题讨论】:
(Spyder dev here) 你能发布一个我可以测试的最小示例吗? 再看上面的帖子... Python Kernel crashes after closing an PyQt4 Gui Application的可能重复 【参考方案1】:要在 Spyder 中再次运行 PyQt 应用程序,必须删除/销毁正在运行的应用程序,但我们不能使用 sys.exit() 因为它会尝试关闭 Python。一种适用于我的解决方案(Python 3.4.1、Spyder 2.3.5.2、PyQt 4.10.4)是使用QtCore.QCoreApplication.instance().quit()
和deleteLater
,如下例所示:
import sys
from PyQt4 import QtGui, QtCore
class Window(QtGui.QMainWindow):
"""PyQt app that closes successfully in Spyder.
"""
def __init__(self):
super().__init__()
self.setGeometry(200, 100, 400, 300)
self.button()
def button(self):
btn = QtGui.QPushButton('Quit', self)
btn.setGeometry(150, 125, 100, 50)
btn.clicked.connect(self.quitApp)
def quitApp(self):
QtCore.QCoreApplication.instance().quit()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
app.aboutToQuit.connect(app.deleteLater)
win = Window()
win.show()
app.exec_()
【讨论】:
【参考方案2】:我遇到过同样的问题,但从未真正找到真正的解决方法。但是,我找到了一种解决方法,可以为我解决问题,也适用于 Eelco van Vliet 回答中的示例代码。
问题似乎是 Python 解释器中存储了一个全局 QApplication,它在程序调用之间没有被破坏。我没有在执行开始时实例化一个新的 QApplication,而是检查它是否存在,如果存在,我使用现有的而不是创建一个新的:
if __name__=="__main__":
if QCoreApplication.instance() != None:
app = QCoreApplication.instance()
else:
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
【讨论】:
【参考方案3】:这实际上似乎是 IPython 内核及其与 PyQt 交互的问题。基本上,IPython 似乎挂在 Qt 实例上,需要在重新实例化之前清除它。这可以通过将保存 Qt 实例的变量重新绑定到其他东西来非常简单地完成:
app = 0
app = QtGui.QApplication([])
...
sys.exit(app.exec_())
这是从here 派生的,而here 是从here 派生的(并且得到了更充分的解释)。
【讨论】:
【参考方案4】:我遇到了同样的问题。下面的简单示例重现了该问题(使用 python 3.4)
当您第一次运行它时,关闭窗口并第二次运行失败。您可以在 spyder 中使用重置内核,但这会减慢开发时间。
对我有用的是输入
%重置
在当前内核的命令行上。这将重置变量 QtCriticalMsg、QtSystemMsg 等。之后您可以重新运行代码。
虽然这比重新启动内核要快一些,但还是很烦人。显然,关闭窗口后 Qt 变量不会从内存中清除。有人建议如何在退出后从程序中强制清理内存?这可能会避免每次都输入 reset 并解决问题
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Form(QDialog):
def __init__(self, parent=None):
super(Form, self).__init__(parent)
self.setAttribute(Qt.WA_DeleteOnClose)
buttonBox = QDialogButtonBox(QDialogButtonBox.Ok|
QDialogButtonBox.Cancel)
grid = QGridLayout()
grid.addWidget(buttonBox, 4, 0, 1, 2)
self.setLayout(grid)
self.connect(buttonBox, SIGNAL("accepted()"),
self, SLOT("accept()"))
self.connect(buttonBox, SIGNAL("rejected()"),
self, SLOT("reject()"))
self.setWindowTitle("Set Number Format (Modal)")
if __name__=="__main__":
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
【讨论】:
以上是关于在 spyder 中从一个提示符运行 pyqt 应用程序两次的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Miniconda 没有运行最新版本的 Spyder?
Spyder启动报错:ModuleNotFoundError: No module named ‘PyQt5.QtWebKitWidgets‘ 解决方法