我正在尝试将三态复选框实现到 QMenu 中。我的菜单层次结构将类似于:
menuA
|-- a101
|-- a102
menuB
|-- b101
其中第一层(menuA,menuB)是三态复选框,而其子项是普通复选框,使用 QAction 实现。
因此,使用QWidgetAction
and QCheckBox
,似乎我可以让三态在第一层工作。
但是,一旦我尝试使用setMenu
包含子项目的第一层项目,即使它能够相应地显示子项目,这些选项也不再可检查。
最初我只使用 QAction 小部件,但是当我迭代子项目时,第一层项目总是显示为一个完整的检查,如果可能的话我想纠正它,因此我试图利用三态.
例如。如果a101
选中,menuA
将设置为部分状态。如果两者a101
都a102
选中,menuA
则将设置为(完整)检查状态。
class CustomCheckBox(QtGui.QCheckBox):
def __init__(self, text="", parent=None):
super(CustomCheckBox, self).__init__(text, parent=parent)
self.setText(text)
self.setTristate(True)
class QSubAction(QtGui.QAction):
def __init__(self, text="", parent=None):
super(QSubAction, self).__init__(text, parent)
self.setCheckable(True)
self.toggled.connect(self.checkbox_toggle)
def checkbox_toggle(self, value):
print value
class QCustomMenu(QtGui.QMenu):
"""Customized QMenu."""
def __init__(self, title, parent=None):
super(QCustomMenu, self).__init__(title=str(title), parent=parent)
self.setup_menu()
def mousePressEvent(self,event):
action = self.activeAction()
if not isinstance(action,QSubAction) and action is not None:
action.trigger()
return
elif isinstance(action,QSubAction):
action.toggle()
return
return QtGui.QMenu.mousePressEvent(self,event)
def setup_menu(self):
self.setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)
def contextMenuEvent(self, event):
no_right_click = [QAddAction]
if any([isinstance(self.actionAt(event.pos()), instance) for instance in no_right_click]):
return
pos = event.pos()
def addAction(self, action):
super(QCustomMenu, self).addAction(action)
class MainApp(QtGui.QWidget):
def __init__(self, parent=None):
super(MainApp, self).__init__(parent)
self.test_dict = {
"testA" :{
"menuA": ["a101", "a102"],
},
"testBC": {
"menuC": ["c101", "c102", "c103"],
"menuB": ["b101"]
},
}
v_layout = QtGui.QVBoxLayout()
self.btn1 = QtGui.QPushButton("TEST BTN1")
v_layout.addWidget(self.btn1)
self.setLayout(v_layout)
self.setup_connections()
def setup_connections(self):
self.btn1.clicked.connect(self.button1_test)
def button1_test(self):
self.qmenu = QCustomMenu(title='', parent=self)
for pk, pv in self.test_dict.items():
base_qmenu = QCustomMenu(title=pk, parent=self)
base_checkbox = CustomCheckBox(pk, base_qmenu)
base_action = QtGui.QWidgetAction(base_checkbox)
base_action.setMenu(base_qmenu) # This is causing the option un-checkable
base_action.setDefaultWidget(base_checkbox)
self.qmenu.addAction(base_action)
for v in pv:
action = QSubAction(v, self)
base_qmenu.addAction(action)
self.qmenu.exec_(QtGui.QCursor.pos())
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
w = MainApp()
w.show()
sys.exit(app.exec_())