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!
Related
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
I am creating an app using PyQt4. I have created two interfaces with Qt Designer. When a button is pushed I would like to switch between one layout and the other.
A sample of my code is:
from PyQt4 import QtGui, uic
form_class = uic.loadUiType("sample.ui")[0]
form_class2 = uic.loadUiType("sample2.ui")[0]
class SecondLayout(form_class2, QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
form_class2.setupUi(self)
class MainWindow(form_class, QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.btn.clicked.connect(self.open_new_window)
def open_new_window(self):
self.Window = SecondLayout()
# here I would like to switch the layout with a layout of self.Window
app = QtGui.QApplication(sys.argv)
myWindow = MainWindow(None)
myWindow.show()
app.exec_()
I have done a lot of searching and reading about QStackedLayout, but haven't been able to get it to work with layouts created in Qt Designer.
My Question is how would I be able to have one Main Window and switch its central widget but i'm not sure if that would work for the seperate menus. I have defined all the menus and widgets and status bars, etc. in Qt Designer as two different projects(both main windows) so I would like to have the main program in one of the main windows, then at some point create an instance of the second main window and switch the layout and all the widgets, menus, text edits, etc. I tried using setCentralWidget but hasn't worked for me.
Could someone please explain to me how to do this.
It sounds like you have two completely separate main windows. There is really no point in switching all the widgets, menus, toolbars, etc, because they will have no shared code. You might just as well simply hide one window, and then show the other one.
Here is a simple demo that shows one way to do that:
PyQt5
from PyQt5 import QtWidgets
class Window1(QtWidgets.QMainWindow):
def __init__(self, window2=None):
super(Window1, self).__init__()
self.setGeometry(500, 100, 100, 50)
self.button = QtWidgets.QPushButton('Go To Window 2', self)
self.button.clicked.connect(self.handleButton)
self.setCentralWidget(self.button)
self._window2 = window2
def handleButton(self):
self.hide()
if self._window2 is None:
self._window2 = Window2(self)
self._window2.show()
class Window2(QtWidgets.QMainWindow):
def __init__(self, window1=None):
super(Window2, self).__init__()
self.setGeometry(500, 100, 100, 50)
self.button = QtWidgets.QPushButton('Go To Window 1', self)
self.button.clicked.connect(self.handleButton)
self.setCentralWidget(self.button)
self._window1 = window1
def handleButton(self):
self.hide()
if self._window1 is None:
self._window1 = Window1(self)
self._window1.show()
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = Window1()
window.show()
sys.exit(app.exec_())
PyQt4
from PyQt4 import QtCore, QtGui
class Window1(QtGui.QMainWindow):
def __init__(self, window2=None):
super(Window1, self).__init__()
self.setGeometry(500, 100, 100, 50)
self.button = QtGui.QPushButton('Go To Window 2', self)
self.button.clicked.connect(self.handleButton)
self.setCentralWidget(self.button)
self._window2 = window2
def handleButton(self):
self.hide()
if self._window2 is None:
self._window2 = Window2(self)
self._window2.show()
class Window2(QtGui.QMainWindow):
def __init__(self, window1=None):
super(Window2, self).__init__()
self.setGeometry(500, 100, 100, 50)
self.button = QtGui.QPushButton('Go To Window 1', self)
self.button.clicked.connect(self.handleButton)
self.setCentralWidget(self.button)
self._window1 = window1
def handleButton(self):
self.hide()
if self._window1 is None:
self._window1 = Window1(self)
self._window1.show()
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window1()
window.show()
sys.exit(app.exec_())
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()
Running this code creates a simple dialog with a label, lineedit and two buttons.
All the widgets beautifully respond to the dialog horizontal resizing. But the buttons at the bottom of the dialog do not stick to the lower edge of dialog window when it is being resized vertically. What would be a possible solution to make sure the buttons are always positioned at the bottom edge of dialog?
from PyQt4 import QtCore, QtGui
app = QtGui.QApplication(sys.argv)
class mainWindow(QtGui.QMainWindow):
def __init__(self):
super(mainWindow, self).__init__()
mainQWidget = QtGui.QWidget()
mainLayout=QtGui.QFormLayout()
mainLayout.setFieldGrowthPolicy(QtGui.QFormLayout.AllNonFixedFieldsGrow)
label = QtGui.QLabel('My Label')
lineEdit = QtGui.QLineEdit()
mainLayout.addRow(label, lineEdit)
ButtonBox = QtGui.QGroupBox()
ButtonsLayout = QtGui.QHBoxLayout()
Button_01 = QtGui.QPushButton("Close")
Button_02 = QtGui.QPushButton("Execute")
ButtonsLayout.addWidget(Button_01)
ButtonsLayout.addWidget(Button_02)
ButtonBox.setLayout(ButtonsLayout)
mainLayout.addRow(ButtonBox)
mainQWidget.setLayout(mainLayout)
self.setCentralWidget(mainQWidget)
if __name__ == '__main__':
window = mainWindow()
window.show()
window.raise_()
window.resize(480,320)
app.exec_()
I would suggest using a QVBoxLayout as your main layout, with a stretch between the QFormLayout and the button's QHBoxLayout.
As an example based on your current dialog:
import sys
from PyQt4 import QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
label = QtGui.QLabel('My Label')
line_edit = QtGui.QLineEdit()
form_layout = QtGui.QFormLayout()
form_layout.addRow(label, line_edit)
close_button = QtGui.QPushButton('Close')
execute_button = QtGui.QPushButton('Execute')
button_layout = QtGui.QHBoxLayout()
button_layout.addWidget(close_button)
button_layout.addWidget(execute_button)
main_layout = QtGui.QVBoxLayout()
main_layout.addLayout(form_layout)
main_layout.addStretch()
main_layout.addLayout(button_layout)
central_widget = QtGui.QWidget()
central_widget.setLayout(main_layout)
self.setCentralWidget(central_widget)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.resize(480, 320)
window.show()
sys.exit(app.exec_())
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.