Запуск приложения pyqt дважды из одной подсказки в spyder

Я запускаю приложение pyqt4 в spyder, выхожу с помощью QtGui.QMainWindow.close(), и оно возвращает меня к подсказке spyder python interpreter. Однако, если я попытаюсь снова запустить приложение runfile('C:/Python33/~/qtapp.py', wdir=r'C:/Python33/~/Appdir'), окно не появится. Мне нужно закрыть окно интерпретатора Python и открыть новое, прежде чем я смогу снова запустить свое приложение pyqt4. Это подсказывает мне, что я есть.

  1. Не правильно закрыть приложение
  2. Не работает приложение правильно

Я хочу иметь возможность запускать приложение 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, 16 мая 2013 г., 00:03:43) [MSC v.1600 32 бит (Intel)] на win32 Введите «help», «авторское право», «кредиты» или «лицензия» за дополнительной информацией.

Импортированы NumPy 1.7.1, SciPy 0.12.0, Matplotlib 1.3.0 + guidata 1.6.1, guiqwt 2.3.1 Введите «научный» для получения более подробной информации.


person Voltage Spike    schedule 18.10.2013    source источник
comment
(Spyder dev здесь) Не могли бы вы опубликовать минимальный пример, который я могу протестировать на своей стороне?   -  person Carlos Cordoba    schedule 19.10.2013
comment
Еще раз смотри пост выше...   -  person Voltage Spike    schedule 23.10.2013


Ответы (4)


Чтобы снова запустить приложение PyQt в Spyder, работающее приложение должно быть удалено/уничтожено, но мы не можем использовать 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_()
person Marcos    schedule 25.07.2015

Я столкнулся с той же проблемой, но так и не нашел истинного решения. Тем не менее, я нашел обходной путь, который решает проблему для меня, а также работает для примера кода в ответе Элко ван Влита.

Проблема, похоже, в том, что в интерпретаторе Python хранится глобальное приложение QApplication, которое не уничтожается между вызовами программы. Вместо создания экземпляра нового QApplication в начале выполнения я проверяю, существует ли он, и если да, то использую существующий, а не создаю новый:

if __name__=="__main__":
    if QCoreApplication.instance() != None:
        app = QCoreApplication.instance()
    else:
        app = QApplication(sys.argv)
    form = Form()
    form.show()
    app.exec_()
person Chris Jackson    schedule 23.03.2015

На самом деле это похоже на проблему с ядром IPython и его взаимодействием с PyQt. По сути, IPython, кажется, цепляется за экземпляр Qt, и его необходимо очистить перед повторным созданием. Это можно сделать очень просто, перепривязав переменную, содержащую экземпляр Qt, к чему-то другому:

app = 0
app = QtGui.QApplication([])
...
sys.exit(app.exec_())

Это получено из здесь, которое получено из (и более подробное объяснение) здесь.

person pattivacek    schedule 24.01.2017

У меня такая же проблема. Простой пример ниже воспроизводит проблему (с использованием 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_()
person Eelco van Vliet    schedule 31.01.2015