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()
Related
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()
I'm writing a small PyQt application that needs to run a few checks before the application starts and if any of the checks fail, the application needs to inform the user it can't run and then quit.
In WinForms. I can achieve this simply:
var form = new Form();
form.Activated += (s, e) =>
{
var condition = true;
if (condition)
{
MessageBox.Show("oh dear, something's wrong.");
Application.Exit();
}
};
PyQt doesn't seem to have a signal that can be connected to when the main application window has loaded and my current attempts don't even fire off the dialog when the condition fails.
This is what I have at the moment (MRE(. Program flow is as follows:
import sys
import winreg
from PyQt5.QtWidgets import QApplication, QWidget, QMessageBox
class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
def loadData(self):
try:
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\Path\To\Nonexistant\Key')
x = winreg.QueryValueEx(key, 'some_key')[0]
print(x)
except FileNotFoundError:
error = QMessageBox()
error.setIcon(QMessageBox.Critical)
error.setText('Cannot locate installation directory.')
error.setWindowTitle('Cannot find registry key')
error.setStandardButtons(QMessageBox.Ok)
error.show()
QApplication.quit()
def main():
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
main_window.loadData()
sys.exit(app.exec_())
main()
My end goal is to be able to let loadData() run when the application has loaded fully and is displayed to the user.
Update: Program now works as expected. I had to:
Change error.show() to error.exec_()
Change QApplication.quit() to sys.exit()
Call main_window.loadData() after main_window.show()
The show method is not blocking, so as soon as it is executed, the QMessageBox will be displayed at QApplication.quit(), instead you should use exec_() that will wait until the user closes the QMessageBox through the buttons.
# ...
error.setStandardButtons(QMessageBox.Ok)
# error.show()
error.exec_()
QApplication.quit()
Update:
On the other hand, QApplication.quit() cannot be used when the eventloop is not started yet, so the solution in this case is to remove the application a moment later using QTimer.singleShot():
class MainWindow(QWidget):
# UI stuff omitted...
def loadData(self):
try:
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\Path\To\Key')
path = winreg.QueryValueEx(key, 'install_path')[0]
# I'll do stuff with path here...
except FileNotFoundError:
error = QMessageBox()
error.setIcon(QMessageBox.Critical)
error.setText('Cannot locate directory.')
error.setWindowTitle('Cannot find registry key')
error.setStandardButtons(QMessageBox.Ok)
error.exec_()
QTimer.singleShot(0, QApplication.quit)
def main():
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
main_window.loadData()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Another equivalent code is as follows
class MainWindow(QWidget):
# UI stuff omitted...
def loadData(self):
try:
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\Path\To\Key')
path = winreg.QueryValueEx(key, 'install_path')[0]
# I'll do stuff with path here...
except FileNotFoundError:
error = QMessageBox()
error.setIcon(QMessageBox.Critical)
error.setText('Cannot locate directory.')
error.setWindowTitle('Cannot find registry key')
error.setStandardButtons(QMessageBox.Ok)
error.exec_()
QApplication.quit()
def main():
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
QTimer.singleShot(0, main_window.loadData)
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I have problem with QTDesigner 5, which should be trivial, but I just can't figure out the problem.
What I want to do is to open a second Window when clicking on a button:
I have designed the Main Window and the secondary one with QTDesigner (PyQT5!) and converted them with pyuic to .py files. The Main Window opens without problems with the following Code:
from PyQt5 import QtGui, QtWidgets, QtCore, uic
import UI14 as UIImport
import GIPrompt as GIImport
class MainWindow(UIImport.Ui_MainWindow):
def __init__(self, window):
UIImport.Ui_MainWindow.__init__(self)
self.setupUi(window)
self.radioButtonGI.clicked.connect(self.openGIPrompt)
def openGIPrompt(self):
windowGI = QtWidgets.QDialog()
Gi = GIPrompt(windowGI)
windowGI.show()
class GIPrompt(GIImport.Ui_GIPrompt):
def __init__(self, windowGI):
GIImport.Ui_GIPrompt.__init__(self)
self.setupUi(windowGI)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = QtWidgets.QMainWindow()
prog = MainWindow(window)
window.show()
sys.exit(app.exec_())
If I add the following to the main function, the "GiPrompt" Window opens as well along with the Main Window:
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = QtWidgets.QMainWindow()
prog = MainWindow(window)
window.show()
"""Open secondWindow"""
windowGI = QtWidgets.QDialog()
Gi = GIPrompt(windowGI)
windowGI.show()
sys.exit(app.exec_())
If I try to open the second window via the openGIPrompt function, nothing happens. I do not get an error message, and no window appears. A print command however tells me that the init_function of the second Window is called...
Has someone an idea, what the problem could be?
Thanks in advance!
I have figured out the problem:
Apparently, the initialized Window is disposed of by garbage collection, as the variables are not declared as self:
This fixed the problem:
from PyQt5 import QtGui, QtWidgets, QtCore, uic
import UI14 as UIImport
import GIPrompt as GIImport
class MainWindow(UIImport.Ui_MainWindow):
windowGI=None
Gi=None
def __init__(self, window):
UIImport.Ui_MainWindow.__init__(self)
self.setupUi(window)
self.radioButtonGI.clicked.connect(self.openGIPrompt)
def openGIPrompt(self):
self.windowGI = QtWidgets.QDialog()
self.Gi = GIPrompt(self.windowGI)
self.windowGI.show()
class GIPrompt(GIImport.Ui_GIPrompt):
def __init__(self, windowGI):
GIImport.Ui_GIPrompt.__init__(self)
self.setupUi(windowGI)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = QtWidgets.QMainWindow()
prog = MainWindow(window)
window.show()
sys.exit(app.exec_())
I study this tutorial http://zetcode.com/gui/pyqt5/firstprograms/
and code here.
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QIcon
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 300, 220)
self.setWindowTitle('Icon')
self.setWindowIcon(QIcon('web.png'))
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Can I show Window icon? I use PyQt5, Python3.4 and Linuxmint 17.2 cinnamon.
i am not sure, what you expected:
the windowicon is shown as applicationIcon (e.g. here on ubuntu gnome, see my code in the background)
If no icon has been set, windowIcon() returns the application icon
(QApplication::windowIcon()).
http://doc.qt.io/qt-5/qwidget.html#windowIcon-prop
looks on ubuntu like this:
so i think, the code is working correctly
Check where the icon file is placed. It should be placed in the execution directory in your case. You can check the execution directroy with the following change:
if __name__ == '__main__':
import os
print("Work dir:" + os.getcwd())
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
try PySide.QtGui.QApplication.setWindowIcon(icon). Like this:
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setWindowIcon(QIcon('web.png'))
ex = Example()
sys.exit(app.exec_())
I faced the exact same problem.
First things first. There is no setWindowIcon() method under QWidget or QMainWindow classes, in fact. you should be trying to set the QIcon at the Application level as follows.
app = QApplication(sys.argv)
app.setWindowIcon(QtGui.QIcon('home.png'))
Second, the icon thus created using this code does not reflect on the title of the window, instead it will reflect as an application icon as shown in the image below. the home.png
Application icon in Mac not the Window Icon
Finally, the path does not really matter, it can be an absolute path or a relative path, the system will consider either.
I'm writing in python using Qt
I want to create the application window (with decorations) to occupy the full screen size. Currently this is the code I have:
avGeom = QtGui.QDesktopWidget().availableGeometry()
self.setGeometry(avGeom)
the problem is that it ignores window decorations so the frame is larger... I googled and what not, found this:
http://harmattan-dev.nokia.com/docs/library/html/qt4/application-windows.html#window-geometry
which seems to indicate I need to set the frameGeometry to the avGeom however I haven't found a way to do that. Also, in the comments in the above link it says what I'm after may not be even possible as the programme can't set the frameGeometry before running... If that is the case I just want confirmation that my problem is not solvable.
EDIT:
So I played around with the code a bit and this gives what I want... however the number 24 is basically through trial and error until the window title is visible.... I want some better way to do this... which is window manager independent..
avGeom = QtGui.QDesktopWidget().availableGeometry()
avGeom.setTop(24)
self.setGeometry(avGeom)
Now I can do what I want but purely out of trial and error
Running Ubuntu, using Spyder as an IDE
thanks
Use QtGui.QApplication().desktop().availableGeometry() for the size of the window:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from PyQt4 import QtGui, QtCore
class MyWindow(QtGui.QWidget):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
self.pushButtonClose = QtGui.QPushButton(self)
self.pushButtonClose.setText("Close")
self.pushButtonClose.clicked.connect(self.on_pushButtonClose_clicked)
self.layoutVertical = QtGui.QVBoxLayout(self)
self.layoutVertical.addWidget(self.pushButtonClose)
titleBarHeight = self.style().pixelMetric(
QtGui.QStyle.PM_TitleBarHeight,
QtGui.QStyleOptionTitleBar(),
self
)
geometry = app.desktop().availableGeometry()
geometry.setHeight(geometry.height() - (titleBarHeight*2))
self.setGeometry(geometry)
#QtCore.pyqtSlot()
def on_pushButtonClose_clicked(self):
QtGui.QApplication.instance().quit()
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
app.setApplicationName('MyWindow')
main = MyWindow()
main.show()
sys.exit(app.exec_())
I've always found inheritting from the QMainWindow class to be particularly useful. Like this:
import sys
from PySide.QtGui import *
from PySide.QtCore import *
class Some_APP(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
### this line here is what you'd be looking for
self.setWindowState(Qt.WindowMaximized)
###
self.show()
def main():
app = QApplication(sys.argv)
some_app = Some_APP()
sys.exit(app.exec_())
if __name__ == "__main__":
main()