Restarting PyQt app in PyCharm with QProcess - python

Button click starts a new detached process of the same app. However, when launched from PyCharm, it crashes on second restart. Print is no longer visible after restart as well.
I want my app to be able to restart many times when launched from either PyCharm or cmd.
import sys, os
from PyQt5.QtCore import QProcess
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
button = QPushButton("Restart")
button.clicked.connect(self.restart)
self.setCentralWidget(button)
def restart(self):
print("Restart")
self.close()
proc = QProcess()
proc.startDetached(sys.executable, sys.argv)
def main():
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
if __name__ == "__main__":
main()

Related

Why is my next page button in python not working?

I followed a GUI course but the exact code does not work for me. I was trying to be guided to the next page when I clicked the button. But every time I click it, Python stops working with:
Process finished with exit code -1073740791 (0xC0000409)
Here's the code:
import sys
from PyQt5.uic import loadUi
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QDialog, QApplication, QMainWindow
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
loadUi("screen1.ui", self)
self.button.clicked.connect(self.gotoScreen2)
def gotoScreen2(self):
widget.setCurrentIndex(widget.currentWidget()+1)
class Screen2(QMainWindow):
def __init__(self):
super(Screen2, self).__init__()
loadUi("screen2.ui",self)
self.button2.clicked.connect(self.gotoScreen1)
def gotoScreen1(self):
widget.setCurrentIndex(widget.currentWidget()+1)
if __name__ == "__main__":
app = QApplication(sys.argv)
widget = QtWidgets.QStackedWidget()
mainwindow = MainWindow()
widget.addWidget(mainwindow)
screen2 = Screen2()
widget.addWidget(screen2)
widget.setFixedWidth(600)
widget.setFixedWidth(800)
widget.show()
try:
sys.exit(app.exec())
except:
print("Exiting..")
There may be some errors in code. It's my first time working on a GUI.
I have changed the
widget.setCurrentIndex(widget.currentWidget()+1)
to
widget.setCurrentIndex(1)
and it solved my problem. Now I can switch between pages without any crashes.
You have to install a module named 'PyQt5'

How to reboot PyQt5 application

I'm trying to restart my application after an update from the client side. I was able to achieve till the auto update part. I tried to surf on How to restart PyQt application?. There are few similar questions earlier, but none of them have good explanation or example with a button click event. Could you guys help me understand on how to reboot a PyQt application. Basically I want to restart the application from if __name__ == '__main__': everytime there is an update.
Note: AppLogin is my private module I created to handle application login. So basically that would be the landing QDialog once application is opened.
from PyQt5.QtWidgets import *
import sys
import AppLogin
class App:
def __init__(self):
btn = QPushButton(main_window)
btn.setText('close')
btn.pressed.connect(self.restart)
main_window.show()
def restart(self):
# Here goes the code for restart
pass
if __name__ == '__main__':
appctxt = QApplication(sys.argv)
log_in = AppLogin.Login()
if log_in.exec_() == QDialog.Accepted:
main_window = QMainWindow()
ui = App()
exit_code = appctxt.exec_()
sys.exit(exit_code)
The logic is to end the eventloop and launch the application an instant before it closes:
import sys
from PyQt5 import QtCore, QtWidgets
def restart():
QtCore.QCoreApplication.quit()
status = QtCore.QProcess.startDetached(sys.executable, sys.argv)
print(status)
def main():
app = QtWidgets.QApplication(sys.argv)
print("[PID]:", QtCore.QCoreApplication.applicationPid())
window = QtWidgets.QMainWindow()
window.show()
button = QtWidgets.QPushButton("Restart")
button.clicked.connect(restart)
window.setCentralWidget(button)
sys.exit(app.exec_())
if __name__ == "__main__":
main()
A solution is to close (or forget) the QMainWindow and recreate it.
If you just "show()" a single widget, the same idea works fine.
import sys
import uuid
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton
class MainWindow(QMainWindow):
singleton: 'MainWindow' = None
def __init__(self):
super().__init__()
btn = QPushButton(f'RESTART\n{uuid.uuid4()}')
btn.clicked.connect(MainWindow.restart)
self.setCentralWidget(btn)
self.show()
#staticmethod
def restart():
MainWindow.singleton = MainWindow()
def main():
app = QApplication([])
MainWindow.restart()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

Ignore KeyboardInterrupt after closing a QProcess with a CTRL_C_EVENT

How can I ignore a KeyboardInterrupt after I used a CTRL_C_EVENT in Python? I only need CTRL_C_EVENT to close the Qprocess and not the PyQt5 window. I tried making an exception for KeyboardInterrupt but I still get the error.
I understand that CTRL_C_EVENT isn't the best option, if you want to keep PyQt5 running, however, the QProcess .exe only responds to that command. Can you help me? I made a sample code below:
import sys
import os
from PyQt5.QtWidgets import QMainWindow, QApplication, QHBoxLayout, QPushButton
from PyQt5.QtCore import QProcess
from signal import CTRL_C_EVENT
class main(QMainWindow):
def __init__(self):
super(main, self).__init__()
self.resize(1000, 800)
self.hLayout = QHBoxLayout(self)
self.process = QProcess()
self.stop_btn = QPushButton('stop process')
self.stop_btn.clicked.connect(self.finishProcess)
self.hLayout.addWidget(self.stop_btn )
self.setLayout(self.hLayout)
path = 'C:\...\.exe'
self.processOffline.start(path)
self.pid = self.processOffline.processId()
def finishProcess(self):
os.kill(self.pid, CTRL_C_EVENT)
try:
self.processOffline.waitForFinished()
except KeyboardInterrupt:
pass
if __name__ == '__main__':
app = QApplication(sys.argv)
w = main()
w.show()
sys.exit(app.exec_())

How to run a PyQt app with connexion module?

I want to run a connexion server in a Qt app, but i don't know how doin this.
I've tried stuff like below, but execution is stuck in "connexion loop" and button "close server" won't show unit i ctrl-c connexion server in console... :
import sys, os
import connexion
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QPushButton
connex_app = connexion.App("Hello World")
class OpennoteserverDlg(QPushButton):
def __init__(self, parent=None):
super().__init__(
"&Close Server", parent)
self.clicked.connect(self.close)
self.setWindowTitle("Opennote-server")
app = QApplication(sys.argv)
form = OpennoteserverDlg()
form.show()
app.connex_app = connex_app
app.connex_app.run()
app.exec_()
The run() method is blocking, so it will not allow the GUI event loop to be executed, causing several GUI tasks not to work correctly. The solution is to run the server in another thread
import signal
import sys
import threading
import connexion
from PyQt5.QtWidgets import QApplication, QPushButton
class OpennoteserverDlg(QPushButton):
def __init__(self, parent=None):
super().__init__("&Close Server", parent)
self.clicked.connect(self.close)
self.setWindowTitle("Opennote-server")
def run_server():
connex_app = connexion.App("Hello World")
connex_app.run()
if __name__ == "__main__":
signal.signal(signal.SIGINT, signal.SIG_DFL)
app = QApplication(sys.argv)
form = OpennoteserverDlg()
form.show()
threading.Thread(target=run_server, daemon=True).start()
sys.exit(app.exec_())

PyQt4 GUI to run terminal commands

I'm new to PyQt4 and I have 2 questions.
I want to create a GUI by which for example when I press a button, a terminal command run (e.g. ping www.google.com)
can I import cvlc in part of GUI
to wrap up I want to create a GUI in which when I press a button
cvlc -v v4l2:///dev/video0
runs and the cvlc window is shown in the GUI.
Any help would be appreciated
This will solve first part i.e. when ping button is pressed it pings google.com and the output is displayed on a terminal.
import sys,os
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Window(QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(150, 150, 150,150)
self.ping = QPushButton('Press to ping', self)
self.ping.move(10,20)
self.ping.clicked.connect(self.gotoPing)
def gotoPing(self):
os.system("ping www.google.com")
def main():
app = QApplication(sys.argv)
ex = Window()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

Categories