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
Related
I have a code which runs on KDE system very well.
On Unity (Ubuntu 16.04 LTS) this code produces unexpected result.
Result on Unity:
wrong result on Unity
Bus the same code produces good result on KDE system:
Link to a good result
Question: Why the same code does not work on Unity?
And a code:
import sys
from PyQt4 import QtGui
class SystemTrayIcon(QtGui.QSystemTrayIcon):
def __init__(self, icon, parent=None):
QtGui.QSystemTrayIcon.__init__(self, icon, parent)
menu = QtGui.QMenu(parent)
edit = QtGui.QLineEdit(parent)
edit.setText("Tekstas kuris turi būti atsiradęs čia")
hl = QtGui.QVBoxLayout(parent)
hl.addWidget(QtGui.QLabel("Testuojame"))
hl.addWidget(edit)
w = QtGui.QWidget(parent)
w.setLayout(hl)
wa = QtGui.QWidgetAction(parent)
wa.setDefaultWidget(w)
menu.addAction(wa)
exitAction = menu.addAction("Blabla")
exitAction = menu.addAction("Blabla 2")
self.setContextMenu(menu)
def main():
app = QtGui.QApplication(sys.argv)
w = QtGui.QWidget()
trayIcon = SystemTrayIcon(QtGui.QIcon("icons/close.png"), w)
trayIcon.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I see the same behaviour on KDE 5.26.0 (Qt 5.6.1, Ubuntu 16.10), the defaultWidget is not shown in the context menu, only the (empty) iconText of the QWidgetAction is displayed. The way the context menu is shown is ultimately controlled by the tray (which is specific to the used desktop environment).
To get this to work consitently you can show your menu as a popup menu on activation instead of in the context menu. The difference is that it isn't activated on right click but on left click and that it may look different from the native trays context menu.
Your example would then look like this:
import sys
from PyQt4 import QtGui
class SystemTrayIcon(QtGui.QSystemTrayIcon):
def __init__(self, icon, parent=None):
QtGui.QSystemTrayIcon.__init__(self, icon, parent)
self.menu = menu = QtGui.QMenu()
edit = QtGui.QLineEdit()
edit.setText("Tekstas kuris turi būti atsiradęs čia")
w = QtGui.QWidget()
hl = QtGui.QVBoxLayout()
w.setLayout(hl)
hl.addWidget(QtGui.QLabel("Testuojame"))
hl.addWidget(edit)
wa = QtGui.QWidgetAction(menu)
wa.setDefaultWidget(w)
menu.addAction(wa)
exitAction = menu.addAction("Blabla")
exitAction = menu.addAction("Blabla 2")
self.activated.connect(self.showPopupMenu)
def showPopupMenu(self, reason):
if reason == QtGui.QSystemTrayIcon.Trigger:
self.menu.popup(QtGui.QCursor.pos())
def main():
app = QtGui.QApplication(sys.argv)
trayIcon = SystemTrayIcon(QtGui.QIcon("icons/close.png"))
trayIcon.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
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!
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 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.
Let's say I created two QObject in my interface (ui). I would like to connect these two widgets and let them controling each other depending on their visual status. If one is hidden, the other one must be visible. And vice versa.
Can you help me ? :)
Thanks !
Nico
Possible solution: Sublclass widgets and override hideEvent and showEvent:
#!/usr/bin/env python
import sys
from PyQt4 import QtCore, QtGui
class CustomWidget(QtGui.QLabel):
signal_hided = QtCore.pyqtSignal()
signal_shown = QtCore.pyqtSignal()
def hideEvent(self, event):
print 'hideEvent'
super(CustomWidget, self).hideEvent(event)
self.signal_hided.emit()
def showEvent(self, event):
print 'showEvent'
super(CustomWidget, self).showEvent(event)
self.signal_shown.emit()
class MainWidget(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.widget1 = CustomWidget('Widget1')
self.widget2 = CustomWidget('Widget2')
# connect signals, so if one widget is hidden then other is shown
self.widget1.signal_hided.connect(self.widget2.show)
self.widget2.signal_hided.connect(self.widget1.show)
self.widget2.signal_shown.connect(self.widget1.hide)
self.widget1.signal_shown.connect(self.widget2.hide)
# some test code
self.button = QtGui.QPushButton('test')
layout = QtGui.QVBoxLayout()
layout.addWidget(self.button)
layout.addWidget(self.widget1)
layout.addWidget(self.widget2)
self.setLayout(layout)
self.button.clicked.connect(self.do_test)
def do_test(self):
if self.widget1.isHidden():
self.widget1.show()
else:
self.widget2.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
widget = MainWidget()
widget.resize(640, 480)
widget.show()
sys.exit(app.exec_())