Issue
I am creating a custom toolbar which automatically adds itself to the parent (if present) when initialized.
I would like this custom toolbar to not appear in the context menu. However, something (I don't know what) related to the toolbar shows up, despite using setContextMenuPolicy
:
I can't tell what that context menu item is. My understanding is that any widget, by way of its contextMenuPolicy, can be added to the context menu. Yet there isn't any other widget within the CustomToolBar.
A workaround is to disable the context menu altogether on the MainWindow and create a menu item (e.g. View) which toggles visibility.
import sys
import time
from PyQt5 import QtCore, QtWidgets
class CustomToolBar(QtWidgets.QToolBar):
def __init__(self, parent=None):
super().__init__(parent=parent)
if parent:
self.setParent(parent)
self.parent().addToolBar(QtCore.Qt.BottomToolBarArea, self)
self.setObjectName('Custom ToolBar')
self.setContextMenuPolicy(QtCore.Qt.NoContextMenu)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.counter = 0
self.resize(250, 75)
self.init_widgets()
self.init_layout()
def init_widgets(self):
self.exit_action = QtWidgets.QAction('&Exit', self)
self.exit_action.setShortcut('Ctrl+Q')
self.exit_action.setToolTip('Exit application')
self.exit_action.triggered.connect(self.close)
self.menu = self.menuBar()
self.menu_file = self.menu.addMenu('&File')
self.menu_file.addAction(self.exit_action)
# setting parent to self embeds the custom toolbar in the main window
self.status = CustomToolBar(self)
def init_layout(self):
layout = QtWidgets.QVBoxLayout()
centralWidget = QtWidgets.QWidget()
centralWidget.setLayout(layout)
self.setCentralWidget(centralWidget)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())
Solution
Note: The image does not illustrate correctly if you are clicking on the menuBar or the lower toolBar.
Some widgets don't override the contextMenuEvent method so using self.setContextMenuPolicy(QtCore.Qt.NoContextMenu)
won't work, and that's the case with the QToolBar (and the QMenuBar as well). In those cases the event method must be override and rejected.
Assuming you just want it not to appear in the QToolBar then just use:
class CustomToolBar(QtWidgets.QToolBar):
def __init__(self, parent=None):
super().__init__(parent=parent)
if isinstance(parent, QtWidgets.QMainWindow):
self.setParent(parent)
parent.addToolBar(QtCore.Qt.BottomToolBarArea, self)
self.setObjectName('Custom ToolBar')
def event(self, event):
if event.type() == QtCore.QEvent.ContextMenu:
return True
return super().event(event)
If you also want to do the same for the MenuBar you have to implement a similar logic:
class StatusBar(QtWidgets.QMenuBar):
def event(self, event):
if event.type() == QtCore.QEvent.ContextMenu:
return True
return super().event(event)
Finally, it is advisable to use names that indicate what type of widget it is, so I will change menu to menu_bar:
def init_widgets(self):
self.exit_action = QtWidgets.QAction('&Exit', self)
self.exit_action.setShortcut('Ctrl+Q')
self.exit_action.setToolTip('Exit application')
self.exit_action.triggered.connect(self.close)
self.menu_bar = StatusBar()
self.setMenuBar(self.menu_bar)
self.menu_file = self.menu_bar.addMenu('&File')
self.menu_file.addAction(self.exit_action)
# setting parent to self embeds the custom toolbar in the main window
self.tool_bar = CustomToolBar(self)
Update:
It seems that the objective of the OP is that the QAction associated with the QToolBar implemented in the QMenu of QMainWindow is not shown, so for this it is better to override the createPopupMenu method and remove the QAction and for this it is not necessary to implement a custom QToolBar.
import sys
import uuid
from PyQt5 import QtCore, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.init_widgets()
self.init_layout()
def init_widgets(self):
self.exit_action = QtWidgets.QAction("&Exit", self)
self.exit_action.setShortcut("Ctrl+Q")
self.exit_action.setToolTip("Exit application")
self.exit_action.triggered.connect(self.close)
self.menu_bar = self.menuBar()
self.menu_file = self.menu_bar.addMenu("&File")
self.menu_file.addAction(self.exit_action)
self.custom_toolbar = QtWidgets.QToolBar()
self.addToolBar(QtCore.Qt.BottomToolBarArea, self.custom_toolbar)
self.custom_toolbar.setProperty("hide_action_toolbar", True)
self.dock = QtWidgets.QDockWidget("Dock")
self.addDockWidget(QtCore.Qt.TopDockWidgetArea, self.dock)
def init_layout(self):
layout = QtWidgets.QVBoxLayout()
centralWidget = QtWidgets.QWidget()
centralWidget.setLayout(layout)
self.setCentralWidget(centralWidget)
def createPopupMenu(self):
titles = []
for toolbar in self.findChildren(QtWidgets.QToolBar):
if toolbar.property("hide_action_toolbar") is None:
continue
if toolbar.property("hide_action_toolbar"):
toolbar.setProperty("last_window_title", toolbar.windowTitle())
toolbar.setWindowTitle(uuid.uuid4().hex)
titles.append(toolbar.windowTitle())
else:
toolbar.setWindowTitle(toolbar.property("last_window_title") or "")
menu = super().createPopupMenu()
for action in menu.actions():
if action.text() in titles:
menu.removeAction(action)
return menu
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
main_window = MainWindow()
main_window.resize(640, 480)
main_window.show()
sys.exit(app.exec_())
Answered By - eyllanesc
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.