如何在QTabWidget中为pyqt设置上下文菜单?

How to set ContextMenu in QTabWidget for pyqt?

我想在QTabWidget上面设置Context Menu,所以继承了QTabBar重写了mousePressEvent函数,然后在QTabWidget中设置setTabBar(),虽然这样可以实现,但是self.setTabsClosable(True)方法似乎无效,我在TabBar上看不到Tab Closed按钮。

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtCore import Qt


class TabBar(QTabBar):
    middleClicked = pyqtSignal(int)

    def __init__(self):
        super(QTabBar, self).__init__()
        self.previousMiddleIndex = -1
        # self.setTabsClosable(True)

    def mousePressEvent(self, mouseEvent):
        if mouseEvent.button() == Qt.RightButton:
            print("Context_menu is OK.")
        QTabBar.mousePressEvent(self, mouseEvent)


class TabDemo(QTabWidget):
    def __init__(self, parent=None):
        super(TabDemo, self).__init__(parent)
        self.tbar = TabBar()
        self.setTabBar(self.tbar)
        self.tab1 = QWidget()
        self.tab2 = QWidget()
        self.addTab(self.tab1, "Tab 1")
        self.addTab(self.tab2, "Tab 2")
        self.tab1UI()
        self.tab2UI()
        self.setWindowTitle("Tab case")
        self.setDocumentMode(True)
        self.setTabsClosable(True)

    def tab1UI(self):
        layout = QFormLayout()
        layout.addRow("name", QLineEdit())
        self.setTabText(0, "contact")
        self.tab1.setLayout(layout)

    def tab2UI(self):
        layout = QFormLayout()
        sex = QHBoxLayout()
        sex.addWidget(QRadioButton("man"))
        sex.addWidget(QRadioButton("woman"))
        self.tab2.setLayout(layout)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = TabDemo()
    demo.show()
    sys.exit(app.exec_())

一些复杂的 QWidget 可以通过设置备用 child 小部件进行自定义,有时需要使用将要添加到的 parent 初始化这些 children;一些示例包括 QAbstractScrollArea 后代(QTextEdit、QGraphicsView 等)的滚动条、项目视图的 headers、QComboBox 的视图,显然还有 QTabWidget 的标签栏。

虽然在大多数情况下这不是强制性的,但最好记住这一点,因为一些特定的(在某些情况下,依赖于平台的)配置会根据状态自动添加到 child 小部件parent.
这就是为 QTabWidget 设置备用 QTabBar 的情况,特别是在 MacOs 上(我想这是由于一些关于如何在此平台上处理选项卡小部件的平台问题)。

这将解决问题:

class TabBar(QTabBar):
    def __init__(self, parent=None):
        super(QTabBar, self).__init__(parent)

class TabDemo(QTabWidget):
    def __init__(self, parent=None):
        super(TabDemo, self).__init__(parent)
        self.tbar = TabBar(self)
        self.setTabBar(self.tbar)
        self.setDocumentMode(True)
        self.setTabsClosable(True)

有一个 reported bug 正是关于这个;它仍然被标记为未解决,但我认为这只是因为(正如报告它的用户所说)设置 parent 解决了问题。