PyQt 5 error on exit - python

I am having an error when I exit my GUI:
Error: "python.exe has stopped working"
This happens when I exit using the topmenu and toolbar exit option. And it also happens when I close the program on the "X" on the top right.
However when I comment the line:
self.mainToolBar.addAction(exitAction)
The "X" on the top right wont give this error.
For the exit option on the toolbar and top menu I am using this:
exitAction.triggered.connect(qApp.quit)
Follow the code:
class Example(QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.topmenu()
self.toolbar()
self.resize(800, 600)
self.setWindowTitle('Example')
self.setWindowIcon(QtGui.QIcon('test.gif'))
self.show()
def topmenu(self):
#Buttons
exitAction = QAction(QtGui.QIcon('plus.gif'), '&Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.triggered.connect(qApp.quit)
#Create MenuBar
menubar = self.menuBar()
#Add options
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exitAction)
def toolbar(self):
exitAction = QAction(QtGui.QIcon('plus.gif'), 'Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setToolTip("Exit")
exitAction.triggered.connect(qApp.quit)
self.mainToolBar = QToolBar(self)
self.mainToolBar.setObjectName("mainToolBar")
self.addToolBar(Qt.LeftToolBarArea, self.mainToolBar)
# Line is giving the stop problem
self.mainToolBar.addAction(exitAction)
def main():
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
How do I fix this?

I am relatively new to PyQt but wouldn't this work:
exitAction.triggered.connect(self.close) #Fires closeEvent()
Just tested on my machine and it exits cleanly.
See docs

I've done the same like this: QtGui.qApp.quit() , in your case:
exitAction.triggered.connect(QtGui.qApp.quit())
If error still exists, try overriding closeEvent like this:
def closeEvent(self, event):
QtGui.qApp.quit()
event.ignore()
I hope this helps.

Related

PyQt5 on MacOs. Custom QMenuBar added to QMainWindow is not clickable

class MenuBarWidget(QMenuBar):
sig_new_file = pyqtSignal()
sig_open_file = pyqtSignal()
sig_save_file = pyqtSignal()
sig_page_setup = pyqtSignal()
sig_print = pyqtSignal()
sig_exit = pyqtSignal()
sig_status_bar = pyqtSignal(bool)
def __init__(self):
super().__init__()
self.init_menu_file()
# self.init_menu_edit()
# self.init_menu_format()
# self.init_menu_view()
# self.init_menu_help()
# self.set_all_text()
def init_menu_file(self):
self.act_new_file = QAction('File', self)
self.act_new_file.setShortcut(QKeySequence('Ctrl+N'))
self.act_new_file.triggered.connect(lambda: self.sig_new_file.emit())
self.act_open_file = QAction('Open', self)
self.act_open_file.setShortcut(QKeySequence('Ctrl+O'))
self.act_new_file.triggered.connect(lambda: self.sig_open_file.emit())
self.act_save_file = QAction('Save', self)
self.act_save_file.setShortcut(QKeySequence('Ctrl+S'))
self.act_save_file.triggered.connect(lambda: self.sig_save_file.emit())
self.act_print = QAction('Print', self)
self.act_print.setShortcut(QKeySequence('Ctrl+P'))
self.act_print.triggered.connect(lambda: self.sig_print.emit())
self.act_quit = QAction('Quit', self)
self.act_quit.setShortcut(QKeySequence('Ctrl+Q'))
self.act_quit.triggered.connect(lambda: self.sig_exit.emit())
self.menu_file = self.addMenu('&File')
self.menu_file.addAction(self.act_new_file)
self.menu_file.addAction(self.act_open_file)
self.menu_file.addAction(self.act_save_file)
self.menu_file.addSeparator()
self.menu_file.addAction(self.act_print)
self.menu_file.addSeparator()
self.menu_file.addAction(self.act_quit)
if __name__ == '__main__':
class Form(QMainWindow):
sig_new_file = pyqtSignal()
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.resize(640, 480)
self.setWindowTitle('MenuBar')
self.menu = MenuBarWidget()
self.setMenuBar(self.menu)
app = QApplication(sys.argv)
form = Form()
form.show()
exit(app.exec_())
I wanted to make a menubar for a window on MacOs 10.15.6 with PyQt 5.15
I used QMenuBar class for custom menubar ,created some submenus under 'File' Menu and added it to QMainWindow
and I can see global menubar is created on the top of display just like the other MacOs.
I tried both
QMenuBar() , QMainWIndow.setMenuBar()
sub_menu = QAction('Someting else..',self)
fileMenu = QMainWindow.menuBar().addMenu('File')
fileMenu.addAction(sub_menu)
However created global menubar is not clickable. I clicked it but it does not show submenus below 'File' Menu.
But This way using 'setNativeMenuBar(False)' below works fine like Windows Applications but I wanna use native MacOs menubar
QMainWindow.menuBar() and QMainWindow.setNativeMenuBar(False)
Here are images.
https://imgur.com/a/Yp6c9YW
# This worked on PyQt5 on macOS Big Sur (ver 11.6)
# it is the result on painful trial and error
# and reading the Qt Docs
def _createMenuBar(self):
menuBar = self.menuBar()
# File menu
fileMenu = menuBar.addMenu("File")
fileMenu.addAction("New")
save = QAction("Save",self)
save.setShortcut("Ctrl+S")
fileMenu.addAction(save)
quit = QAction("\0Quit",self)
quit.setShortcut("Ctrl+Q")
fileMenu.addAction(quit)
# Edit menu
editMenu = menuBar.addMenu("Edit")
editMenu.addAction("Copy")
editMenu.addAction("Paste")
# Help menu
helpMenu=menuBar.addMenu("Help")
helpMenu.addAction(self.helpContentAction)
helpMenu.addAction(self.aboutAction)
This might help
from PyQt5.QtWidgets import QMenuBar
Mainmenu=self.menuBar();# creates a menu bar widget
Filemenu=Mainmenu.addMenu('file');#this adds file to menubar
Editmenu=Mainmenu.addMenu('Edit');#this adds edit to menubar

Developing a GUI with PySide

I am trying to get buttons and a menu bar inside a GUI application. When I run my code the GUI is seen with the menu bar but the button is not seen. Here is my sample code. And the code compiles without any error.
import sys
from PySide.QtGui import *
from PySide.QtCore import *
class guiwindow(QMainWindow):
def __init__(self):
super(guiwindow,self).__init__()
self.menubar()
def menubar(self):
textEdit = QWidget()
self.setCentralWidget(textEdit)
exitAction = QAction('Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit application')
exitAction.triggered.connect(self.close)
self.statusBar()
menubar = self.menuBar()
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exitAction)
self.setGeometry(400, 100, 1200, 800)
self.setWindowTitle("Menubar + Buttons")
button = QPushButton("Test")
hbox = QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(button)
self.setLayout(hbox)
self.show()
def main():
app = QApplication(sys.argv)
ex = guiwindow()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Generally, in GUI programming you'll have to be faimliar with the concept of parent and child widgets. If you want your button to be inside your window, then the later should be a child of the former.
So use:
button = QPushButton("Test", parent=self)
Instead of:
button = QPushButton("Test")
Hope this helps!

QCoreApplication::exec: The event loop is already running

I just started with programming, started using Python and PyQt4. And got this error:
QCoreApplication::exec: The event loop is already running
Basically i wanted to write a function which, when you press a button, opens a new gui window(while the previous one wouldnt exist at that point) with completely new layout.
Is there a way how to fix the script or write it in another way to get the outcome?
import sys
from PyQt4 import QtGui, QtCore
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(50, 50 , 1280, 720)
self.setWindowTitle("Main")
self.setWindowIcon(QtGui.QIcon("smili.png"))
extractAction = QtGui.QAction("Exit", self)
extractAction.setShortcut("Ctrl+Q")
extractAction.setStatusTip("Press to leave the app.")
extractAction.triggered.connect(self.close_appllication)
self.statusBar()
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu("Menu")
fileMenu.addAction(extractAction)
self.home()
def home(self):
btn = QtGui.QPushButton("Quit", self)
btn.clicked.connect(QtCore.QCoreApplication.instance() .quit)
btn.resize(250,50)
btn.move(100,600)
btn.setStyleSheet('QPushButton{background-color:#8A0808;color:#000000;font-size:25px;border:5px}')
btn = QtGui.QPushButton("Start", self)
btn.clicked.connect(self.redirect_window)
btn.resize(250,50)
btn.move(100,200)
btn.setStyleSheet('QPushButton{background-color:#8A0808;color:#000000;font-size:25px;border:5px}')
extractAction = QtGui.QAction(QtGui.QIcon("exitb.png"), "Exit the application.", self)
extractAction.triggered.connect(self.close_appllication)
self.toolBar = self.addToolBar("ToolBar")
self.toolBar.addAction(extractAction)
checkBox = QtGui.QCheckBox("Enlarge Window", self)
checkBox.move(100, 25)
checkBox.stateChanged.connect(self.enlarge_window)
self.show()
def redirect_window(self):
class startWindow(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(50, 50 , 1280, 720)
self.setWindowTitle("Main/Start")
self.setWindowIcon(QtGui.QIcon("smili.png"))
extractAction = QtGui.QAction("Exit", self)
extractAction.setShortcut("Ctrl+Q")
extractAction.setStatusTip("Press to leave the app.")
extractAction.triggered.connect(self.close_appllication)
self.statusBar()
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu("Menu")
fileMenu.addAction(extractAction)
self.home()
main()
def enlarge_window(self, state):
if state == QtCore.Qt.Checked:
self.setGeometry(50,50,1920,1080)
else:
self.setGeometry(50,50,1280,720)
def close_appllication(self):
print("Shutting down!")
sys.exit()
def main():
app = QtGui.QApplication(sys.argv)
GUI = Window()
sys.exit(app.exec_())
main()

PyQt having a status bar & menu bar QWidget

I am trying to create a PyQt application that has both status bar and a menu bar with other Widgets in the window. Below is the code which I managed to get it run with class QtGui.QMainWindow method. But as I intend to add further features, I realise I must use QtGui.QWidget instead.
Here is the code:
import sys
from PyQt4 import QtGui, QtCore
### How can I use QtGui.QWidget here??? ###
class Example(QtGui.QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
QtGui.QToolTip.setFont(QtGui.QFont('SansSerif', 10))
self.setToolTip('This is a <b>QWidget</b> Window widget')
exitAction = QtGui.QAction(QtGui.QIcon('exit-icon-2.png'), '&Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit/Terminate application')
exitAction.triggered.connect(QtGui.qApp.quit)
self.statusBar()
menubar = self.menuBar()
menubar.setToolTip('This is a <b>QWidget</b> for MenuBar')
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exitAction)
toolbar = self.addToolBar('Exit')
toolbar.addAction(exitAction)
qbtn = QtGui.QPushButton('Quit', self)
qbtn.setToolTip('This is a <b>QPushButton</b> widget')
qbtn.clicked.connect(self.launchAAA)
qbtn.resize(qbtn.sizeHint())
qbtn.move(170, 190)
self.setGeometry(500, 180, 400, 400)
self.setWindowTitle('Quit button with Message')
self.show()
def launchAAA(self, event):
reply = QtGui.QMessageBox.question(self, 'Message',
"Are you sure to quit?", QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
QtGui.QApplication.quit()
else:
pass
def main():
app = QtGui.QApplication(sys.argv)
ex=Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I am under the impression that menu bar and title bars can be created using QWidget method, but here it doesn't work. I intend to add an LCD function to the application using QtGui.QLCDNumber.
Any suggestions on how to fix the above problem. Thanks
You could just move your buttons/labels/etc. to a QWidget, and add this widget to the main window. Here is how it could look like (I changed the imports so that it is a bit more readable).
Your content widget class :
class ExampleContent(QWidget):
def __init__(self, parent):
QWidget.__init__(self, parent)
self.initUI()
def initUI(self):
qbtn = QPushButton('Quit', self)
qbtn.setToolTip('This is a <b>QPushButton</b> widget')
qbtn.clicked.connect(self.launchAAA)
qbtn.resize(qbtn.sizeHint())
qbtn.move(170, 190)
def launchAAA(self):
reply = QMessageBox.question(self, 'Message',
"Are you sure to quit?", QMessageBox.Yes |
QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
QApplication.quit()
else:
pass
Add it to the main window :
class Example(QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
QToolTip.setFont(QFont('SansSerif', 10))
self.setToolTip('This is a <b>QWidget</b> Window widget')
exitAction = QAction(QIcon('exit-icon-2.png'), '&Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit/Terminate application')
exitAction.triggered.connect(qApp.quit)
self.statusBar()
menubar = self.menuBar()
menubar.setToolTip('This is a <b>QWidget</b> for MenuBar')
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exitAction)
toolbar = self.addToolBar('Exit')
toolbar.addAction(exitAction)
# create the widget here
content = ExampleContent(self)
self.setCentralWidget(content)
self.setGeometry(500, 180, 400, 400)
self.setWindowTitle('Quit button with Message')
self.show()
And everything just works as before, except that you new have a QWidget in the middle, instead of a QMainWindow. Hope that helped !
Here is a working solution using your code. I added a centralWidget and a centralLayout to the QMainWindow which now holds your qbtn:
import sys
from PyQt4 import QtGui, QtCore
class Example(QtGui.QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
QtGui.QToolTip.setFont(QtGui.QFont('SansSerif', 10))
self.setToolTip('This is a <b>QWidget</b> Window widget')
exitAction = QtGui.QAction(QtGui.QIcon('exit-icon-2.png'), '&Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit/Terminate application')
exitAction.triggered.connect(QtGui.qApp.quit)
self.statusBar()
menubar = self.menuBar()
menubar.setToolTip('This is a <b>QWidget</b> for MenuBar')
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exitAction)
toolbar = self.addToolBar('Exit')
toolbar.addAction(exitAction)
# Create a central Widgets
centralWidget = QtGui.QWidget()
# Create a Layout for the central Widget
centralLayout = QtGui.QHBoxLayout()
qbtn = QtGui.QPushButton('Quit', self)
qbtn.setToolTip('This is a <b>QPushButton</b> widget')
qbtn.clicked.connect(self.launchAAA)
qbtn.resize(qbtn.sizeHint())
qbtn.move(170, 190)
# Add the Button to the Layout
centralLayout.addWidget(qbtn)
# Set the Layout
centralWidget.setLayout(centralLayout)
# Set the Widget
self.setCentralWidget(centralWidget)
self.setGeometry(500, 180, 400, 400)
self.setWindowTitle('Quit button with Message')
self.show()
def launchAAA(self, event):
reply = QtGui.QMessageBox.question(self, 'Message',
"Are you sure to quit?", QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
QtGui.QApplication.quit()
else:
pass
def main():
app = QtGui.QApplication(sys.argv)
ex=Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
You can also use a combination of QMainWindow and QWidget.
I have found this useful in some cases. You can add statusbar and menubar to the MainWindow section and the widgets to the QWidget area.
import sys
from PyQt4 import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.win_widget = WinWidget(self)
widget = QtGui.QWidget()
layout = QtGui.QVBoxLayout(widget)
layout.addWidget(self.win_widget)
self.setCentralWidget(widget)
self.statusBar().showMessage('Ready')
self.setGeometry(300, 300, 450, 250)
self.setWindowTitle('Test')
self.setWindowIcon (QtGui.QIcon('logo.png'))
self.show()
self.win_widget = WinWidget (self)
class WinWidget (QtGui.QWidget) :
def __init__(self, parent):
super (WinWidget , self).__init__(parent)
self.__controls()
#self.__layout()
def __controls(self):
self.qbtn = QtGui.QPushButton('Quit', self)
self.qbtn. clicked.connect(QtCore.QCoreApplication.instance().quit)
self.qbtn.setFixedSize (100,25)
self.qbtn.move(50, 50)
def main():
app = QtGui.QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

how to hide wxpython status bar by default

I am learning wxpython following the tutorials on zetcode about menu bars and status bars. Please forgive me if the question is stupid.
The code below from the website works fine, but I am curious how to hide the status bar by default (when the application window popup).
import wx
class Example(wx.Frame):
def __init__(self, *args, **kwargs):
super(Example, self).__init__(*args, **kwargs)
self.InitUI()
def InitUI(self):
menubar = wx.MenuBar()
fileMenu = wx.Menu()
viewMenu = wx.Menu()
self.shst = viewMenu.Append(wx.ID_ANY, 'Show statubar',
'Show Statusbar', kind=wx.ITEM_CHECK)
self.shtl = viewMenu.Append(wx.ID_ANY, 'Show toolbar',
'Show Toolbar', kind=wx.ITEM_CHECK)
viewMenu.Check(self.shst.GetId(), True)
viewMenu.Check(self.shtl.GetId(), True)
self.Bind(wx.EVT_MENU, self.ToggleStatusBar, self.shst)
self.Bind(wx.EVT_MENU, self.ToggleToolBar, self.shtl)
menubar.Append(fileMenu, '&File')
menubar.Append(viewMenu, '&View')
self.SetMenuBar(menubar)
self.toolbar = self.CreateToolBar()
self.toolbar.AddLabelTool(1, '', wx.Bitmap('texit.png'))
self.toolbar.Realize()
self.statusbar = self.CreateStatusBar()
self.statusbar.SetStatusText('Ready')
self.SetSize((350, 250))
self.SetTitle('Check menu item')
self.Centre()
self.Show(True)
def ToggleStatusBar(self, e):
if self.shst.IsChecked():
self.statusbar.Show()
else:
self.statusbar.Hide()
def ToggleToolBar(self, e):
if self.shtl.IsChecked():
self.toolbar.Show()
else:
self.toolbar.Hide()
def main():
ex = wx.App()
Example(None)
ex.MainLoop()
if __name__ == '__main__':
main()
I have tried to change one line above into:
viewMenu.Check(self.shst.GetId(), False)
Sadly, that didn't work out.
Willing to hear any advice! Thanks in advance!
Specs: wxpython: 2.8.12.1; python 2.7; Ubuntu 12.04
IMHO, because viewMenu.Check(..) is called before UI initialization is done (before event loop begin), it may not fire event.
How about manually call ToggleStatusBar method after viewMenu.Check?
def InitUI(self):
....
viewMenu.Check(self.shst.GetId(), False)
self.ToggleStatusBar(None)
This might be what you mean by Just curious if any built-in functions can do that kind of "update" job?
There is a wx.EVT_UPDATE_UI event, i've modifed your code to use it.
UpdateUIEvent
import wx
class Example(wx.Frame):
def __init__(self, *args, **kwargs):
super(Example, self).__init__(*args, **kwargs)
self.InitUI()
def InitUI(self):
menubar = wx.MenuBar()
fileMenu = wx.Menu()
viewMenu = wx.Menu()
self.shst = viewMenu.Append(-1, 'Show statubar', 'Show Statusbar',
kind=wx.ITEM_CHECK)
self.shtl = viewMenu.Append(-1, 'Show toolbar', 'Show Toolbar',
kind=wx.ITEM_CHECK)
self.shst.Check(False)
self.shtl.Check(True)
menubar.Append(fileMenu, '&File')
menubar.Append(viewMenu, '&View')
self.SetMenuBar(menubar)
self.toolbar = self.CreateToolBar()
self.toolbar.AddLabelTool(1, '', wx.EmptyBitmap(16, 16))
self.toolbar.Realize()
self.statusbar = self.CreateStatusBar()
self.statusbar.SetStatusText('Ready')
self.Bind(wx.EVT_UPDATE_UI, self.on_update_status_bar, self.statusbar)
self.Bind(wx.EVT_UPDATE_UI, self.on_update_tool_bar, self.toolbar)
self.SetSize((350, 250))
self.SetTitle('Check menu item')
self.Centre()
self.Show(True)
def on_update_status_bar(self, event):
event.Show(self.shst.IsChecked())
def on_update_tool_bar(self, event):
event.Show(self.shtl.IsChecked())
def main():
ex = wx.App()
Example(None)
ex.MainLoop()
if __name__ == '__main__':
main()
I think this way would be better.
statusBarHandle.Hide()
self.SetStatusBar(None) #Disable Status Bar
#Enable
statusBarHandle.Show()
self.SetStatusBar(statusBarHandle) #Back created StatusBar(self.CreateStatusBar function)
#Useful tip: for update all widgets in AUI, use AUI function Update()
#For sizers you need to use the Layout() or Update() function

Categories

Resources