The item showing up in the context menu is, in fact, the toolbar. The menu item comes from the corresponding action text. This, in turn, comes from the toolbar window title. Since this is an empty string by default, it shows as blank in the menu.
Changing the line self.setObjectName('Custom ToolBar')
to self.setWindowTitle('Custom ToolBar')
will show the toolbar name, as expected.

import sys
import time
from PyQt5 import QtCore, QtWidgets
class CustomToolBar(QtWidgets.QToolBar):
def __init__(self, parent=None, title='CustomToolBar'):
super().__init__(parent=parent)
# Sets the action text in the context menu
self.setWindowTitle(title)
if parent:
self.setParent(parent)
self.parent().addToolBar(QtCore.Qt.BottomToolBarArea, self)
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_bar = CustomMenuBar()
# self.setMenuBar(self.menu_bar)
self.menu_bar = self.menuBar()
self.menu_file = self.menu_bar.addMenu('&File')
self.menu_file.addAction(self.exit_action)
# self embeds the 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_())
As for the CustomToolBar not appearing in the context menu, that's more complicated. One option is to use a custom context menu via the parent (i.e. MainWindow). This post explains how that can be done.
However, wanting to have the CustomToolBar automatically remove itself is better for the user, but more of a challenge. The context menu is actually created on the fly by the QMainWindow via the createContextPopupMenu
method. The CustomToolBar has to override this method such that it removes itself from the resulting list. Ideally, this should be done in a way that preserves the context menu's behavior.
The createContextPopupMenu
method is called by the MainWindow's contextMenuEvent
handler. So, using the fact that Python treats functions as first class citizens, we can replace the createPopupMenu
method with a version that removes the CustomToolBar from it. The following example has added a QDockWidget to demonstrate that the CustomToolBar has removed itself.

import sys
import time
from PyQt5 import QtCore, QtWidgets
class CustomToolBar(QtWidgets.QToolBar):
def __init__(self, parent=None, title='CustomToolBar'):
super().__init__(parent=parent)
# Sets the action text in the context menu
self.setWindowTitle(title)
if parent:
self.setParent(parent)
self.parent().addToolBar(QtCore.Qt.BottomToolBarArea, self)
############################################################
# Remove the custom toolbar from the parent's context menu #
############################################################
original_popup = self.parent().createPopupMenu
original_handler = self.parent().contextMenuEvent
# Create custom contextMenuEvent which repurposes the
# original createPopupMenu method through use of closures
def customContextMenuEvent(event):
def custom_popup():
popup = original_popup()
# Because this is being handled by CustomToolBar,
# which adds itself to the MainWindow, there is
# guaranteed to be at least one item
for action in popup.actions():
if action.text() == self.windowTitle():
popup.removeAction(action)
return popup
# call the original handler with its call to
# createPopupMenu sneakily replaced with our own
self.parent().createPopupMenu = custom_popup
original_handler(event)
# Replace the MainWindow's contextMenuEvent with our own
self.parent().contextMenuEvent = customContextMenuEvent
# Prevents right click on CustomToolBar from showing context menu
self.setContextMenuPolicy(QtCore.Qt.PreventContextMenu)
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_bar = self.menuBar()
self.menu_file = self.menu_bar.addMenu('&File')
self.menu_file.addAction(self.exit_action)
# self embeds the status toolbar in the main window
self.status = CustomToolBar(self)
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)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())