Using QProcess.finished() in Python 3 and PyQt - python

How can I use the QProcess.finished() to call a different Python3 script.
Here's the script I call:
#!/usr/bin/python
from PyQt4.QtGui import QApplication
from childcontrolgui import childcontrolgui
def main():
import sys
app = QApplication(sys.argv)
wnd = childcontrolgui()
wnd.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
To call the script I use the code as seen here
def properties(self):
command="python3 ../GUI/main.py"
self.process=QProcess()
self.process.finished.connect(self.onFinished)
self.process.startDetached(command)
def onFinished(self, exitCode, exitStatus):
self.Check_Timer.stop()
self.Logout_Timer.stop()
self.Firstrun=True
self.initControl()
Starting of the process works, the window from main.py is shown, but it seems, finished isn't fired. Nothing happens, when I close the Window from main.py

You can't get a signal when you use startDetached() because you have no object. Use ordinary start() instead.
And don't forget to start QApplication within control script, too.
class Control(QObject):
def properties(self):
self.process=QProcess()
self.process.finished.connect(self.onFinished)
self.process.start('python3', ['../GUI/main.py'])
def onFinished(self, exitCode, exitStatus):
[...]
if __name__ == '__main__':
app = QApplication(sys.argv)
co = Control()
co.properties()
sys.exit(app.exec_())

Related

pyqt5 problem :The new window closes immediately [duplicate]

I am getting an issue when trying to open a PyQt window.
The code below is an example of my original code. When I imported the module in import Test and ran test.Start(), I got the following error:
QCoreApplication::exec: The event loop is already running
After some research, I found out it was because I had already already made a QApplication.
test.py....
import sys
def Start():
app = QApplication(sys.argv)
m = myWindow()
m.show()
app.exec_()
class myWindow():....
if __name__ == "__main__":
Start()
So then I read that I could rewrite my code like this and it would fix the error:
test.py....
def Start():
m = myWindow()
m.show()
class myWindow():....
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
Start()
app.exec_()
Now I no longer get the QCoreApplication::exec: The event loop is already running error, but my window closes almost immediately after opening.
You need to keep a reference to the opened window, otherwise it goes out of scope and is garbage collected, which will destroy the underlying C++ object also. Try:
def Start():
m = myWindow()
m.show()
return m
class myWindow():....
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
window = Start()
app.exec_()
You can also do:
def Start():
global m
m = myWindow()
m.show()
class myWindow():....
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
window = Start()
app.exec_()
Use the following code. Your problem is in your imports and using "show" as a name for function as far as I assume. You haven't provided what you have written in your class, so it's difficult to guess. But following code works like a charm. ;-)
Best wishes, good luck!
import sys
from PyQt5 import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
app = QApplication(sys.argv)
def Start():
m = myWindow()
m.showWid()
sys.exit(app.exec())
class myWindow:
def __init__(self):
self.window = QWidget()
self.window.setWindowTitle("Program Title")
self.window.setFixedWidth(600)
self.window.setStyleSheet("background: #18BEBE;")
def showWid(self):
self.window.show()
if __name__ == "__main__":
Start()

Can't Kill PyQT Window after closing it. Which requires me to restart the kernal

I guess that I am not closing my PyQT5 Window correctly. I am using spyder (3.3.5) which I have installed with anaconda, to program a pyqt5 program. I am using qt creator to design my ui file, which I load using the loadUi function in pyqt package. Everything works fine with the code, until I need to close it. I close the window via the close button (the x button in the top right). The window itself is closed, but it seems like the console (or shell) is stuck, and I can't give it further commands or to re run the program, without having to restart the kernel (to completely close my IDE and re opening it).
I have tried looking for solutions to the problem in the internet, but none seems to work for me. Including changing the IPython Console > Graphics to automatic.
Edit: Also Created an issure:
https://github.com/spyder-ide/spyder/issues/9991
import sys
from PyQt5 import QtWidgets,uic
from PyQt5.QtWidgets import QMainWindow
class Mic_Analysis(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.ui=uic.loadUi("qt_test.ui",self)
...
if __name__ == "__main__":
def run_app():
if not QtWidgets.QApplication.instance():
app = QtWidgets.QApplication(sys.argv)
else:
app=QtWidgets.QApplication.instance()
mainWin=Mic_Analysis()
mainWin.show()
app.exec_()
run_app()
If someone have any suggestion I would be very happy to hear them.
For me, it helped to remove the 'app.exec_()' command.
But then it closes immediatly when running the code. To keep the window open, I needed to return the MainWindow instance to the global scope (or make it a global object). My code looks like this:
from PyQt5 import QtWidgets
import sys
def main():
if not QtWidgets.QApplication.instance():
app = QtWidgets.QApplication(sys.argv)
else:
app = QtWidgets.QApplication.instance()
main = MainWindow()
main.show()
return main
if __name__ == '__main__':
m = main()
Try adding :
app.setQuitOnLastWindowClosed(True)
to your main() function
def main():
app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(True)
win = MainWindow()
win.show()
sys.exit(app.exec_())
Surprizinglly, for me this works well. No QApplication is needed.
It seems to work in another thread.
from PyQt5 import QtWidgets,uic
class Ui(QtWidgets.QDialog):
def __init__(self):
super().__init__()
uic.loadUi('./test.ui',self)
self.show()
w=Ui()

How to keep QMainWindow open?

I have a UI file that I created using Qt Creator. When I execute the application through PyCharm, the main window opens briefly, then closes. I assume it is being garbage collected, but I'm not sure how to get this to work. Any ideas?
Calculator.py
from PyQt5.QtWidgets import QApplication
import MainWindow
import sys
class Calculator(QApplication):
def __init__(self):
args = sys.argv
QApplication.__init__(self, args)
self.initializeApplication()
def initializeApplication(self):
app = MainWindow.MainWindow()
app.show()
if __name__ == '__main__':
app = Calculator()
sys.exit(app.exec_())
MainWindow.py
from PyQt5 import uic
from PyQt5.QtWidgets import QMainWindow
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self, None)
uic.loadUi(r'interface/MainWindow.ui', self)
self.initializeUI()
def initializeUI(self):
self.setWindowTitle('Calculator')
I'm new to Python so please bear with me. I have looked at a few different examples, but nothing that really covers when your application spans multiple source files. Thanks.
The comment that the garbage collector is deleting it is correct since the variables created in a function only exist while the function is called. Also to be able to execute a GUI, you must call exec_() to generate the main loop that is needed.
class Calculator(QApplication):
def __init__(self):
args = sys.argv
QApplication.__init__(self, args)
self.initializeApplication()
self.exec_()
def initializeApplication(self):
self.app = MainWindow.MainWindow()
self.app.show()
if __name__ == '__main__':
app = Calculator()

PyQt5 Interrupt Close Event from Outside the Main Gui Module

I use Qt Designer to build my GUI's and convert them to py files using pyuic5. My end goal here is to interrupt the user from closing the program when a variable == 1 and present them with an 'are you sure you want to close?' type dialog. If said variable == 0 then just close the program normally.
I have seen lots of examples on how to do this, but all of them require editing the code in the GUI module. I import my gui.py file created by pyuic5 into my main script where I do all my connections to buttons, line edits, etc.. I do this so that at anytime I can update the GUI with Qt Designer and not affect the programs functionality.
Is there a way to do this from my main script that has the GUI module from Qt Designer imported?
Example of how my main script is structured:
import philipsControlGui
import sys
def main():
MainWindow.show()
sys.exit(app.exec_())
def test():
print('test')
# Main window setup
app = philipsControlGui.QtWidgets.QApplication(sys.argv)
MainWindow = philipsControlGui.QtWidgets.QMainWindow()
ui = philipsControlGui.Ui_MainWindow()
ui.setupUi(MainWindow)
# Main window bindings
ui.onButton.clicked.connect(test)
### Can I insert something here to do: if user closes the window... do something else instead?
if __name__ == "__main__":
main()
You should create a subclass from your imported gui so you can reimplement the closeEvent method:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from philipsControlGui import Ui_MainWindow
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setUpUi(self)
self.ui.onButton.clicked.connect(self.test)
self._check_close = True
def test(self):
print('test')
self._check_close = not self._check_close
def closeEvent(self, event):
if self._check_close:
result = QtWidgets.QMessageBox.question(
self, 'Confirm Close', 'Are you sure you want to close?',
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
if result == QtWidgets.QMessageBox.Yes:
event.accept()
else:
event.ignore()
def main():
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
If there's a specific 'ExitButton' in your design, you should be able to connect it in the main code and create a pop up dialog. You would have to import the QtCore/QtGui components. I always write my GUI directly (QtDesigner is pain when it comes to these things) so I'm assuming something like this:
from PyQt4.QtGui import *
from PyQt4.QtCore import *
[YOUR CODE]
ui.ExitButton.clicked.connect(Exit)
def Exit():
msg = QMessageBox()
msg.setIcon(QMessageBox.Information)
msg.setText("Are you sure you want to close this window?")
msg.setWindowTitle("MessageBox demo")
msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
msg.buttonClicked.connect(msgbtn)
retval = msg.exec_()
print "value of pressed message box button:", retval

What is the proper way of restarting QApplication?

I'm Working with PySide, and seeking a way to restart my Qt app. Does this depends on python, or it has to be controlled by Qt?
BY ROSTYSLAV'S SUGGESTION BELLOW :
class MyAppMainWindow(QMainWindow):
def __init__(self):
self.EXIT_CODE_REBOOT = -15123123
exit_code = self.EXIT_CODE_REBOOT
def slotReboot(self):
print "Performing application reboot.."
qApp.exit( self.EXIT_CODE_REBOOT )
def main():
currentExitCode = 0
app = QApplication(sys.argv)
ex = MyAppMainWindow()
while currentExitCode == ex.EXIT_CODE_REBOOT :
currentExitCode = app.exec_()
return currentExitCode
if __name__ == '__main__':
main()
Obviously I didn't fully understand. Pleas help.
There's a nice way presented by Qt Wiki on how to make your application restartable.
The approach is based on recreation of QApplication instance and not killing current process.
It can be easily adopted to PySide like the next snippet shows:
EXIT_CODE_REBOOT = -15123123 # you can use any unique value here
exit_code = EXIT_CODE_REBOOT # Just for making cycle run for the first time
while exit_code == EXIT_CODE_REBOOT:
exit_code = 0 # error code - no errors happened
app = QApplication(sys.argv)
...
exit_code = app.exec()
You just need to setup proper exit code through the API presenteed by QApplication before finishing your app. The you can hook up new configuration or whatever you need when new application instance is created.
The topic is quite old, but i see there is no proper solution provided. So here it is (based on what Rostyslav Dzinko suggested):
EXIT_CODE_REBOOT = -11231351
from PySide import QtGui, QtCore
import sys
class MyApp(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MyApp, self).__init__(parent)
def restart (self):
#DO stuff before restarting here
return QtCore.QCoreApplication.exit( EXIT_CODE_REBOOT )
def start_app():
exit_code = 0
while True:
try:
app = QtGui.QApplication(sys.argv)
except RuntimeError:
app = QtCore.QCoreApplication.instance()
myap = MyApp()
myap.show()
exit_code = app.exec_()
if exit_code != EXIT_CODE_REBOOT:
break
return exit_code
if __name__ == '__main__':
start_app()

Categories

Resources