【问题标题】:How to make QCombobox expandable for hierarchical items?如何使 QCombobox 可扩展用于分层项目?
【发布时间】:2019-03-13 05:13:12
【问题描述】:

我有一些字典变量,例如:

{"Courses" : ["Math" , "Science" , "English"]} , 
{"Cars" : ["Ford" , "BMW" , "Mercedes"]} , etc.

我想从 qcombobox 中选择值,但首先,我需要将光标保持在 qcombobox 中的键上,然后从突出显示的键中选择值。

Courses
Cars-->Ford
    -->BMW
    -->Mercedes

我怎么能做这样的事情? 谢谢回复。

【问题讨论】:

    标签: python pyqt pyqt4 pyqt5 qcombobox


    【解决方案1】:

    您可以使用QPushButtonQMenu,如下所示:

    PyQt4:

    from PyQt4 import QtCore, QtGui
    
    data =[{
            "Courses": ["Math", "Science", "English"]
        },
        {
            "Cars": ["Ford", "BMW", "Mercedes"]
        }
    ]
    
    class ComboBoxExpandable(QtGui.QPushButton):
        currentTextChanged = QtCore.pyqtSignal(str)
        pathChanged = QtCore.pyqtSignal(list)
    
        def setData(self, value):
            menu = QtGui.QMenu(self)
            self.setMenu(menu)
            self.append_element(value, menu)
            menu.triggered.connect(self.on_triggered)
    
        @QtCore.pyqtSlot(QtGui.QAction)
        def on_triggered(self, action):
            self.setText(action.text())
            path = [action.text()] 
            w = action.parentWidget()
            while w.parentWidget() and isinstance(w.parentWidget(), QtGui.QMenu):
                path.insert(0, w.title())
                w = w.parentWidget()
            self.pathChanged.emit(path)
            self.currentTextChanged.emit(self.text())
    
        @staticmethod
        def append_element(value, menu):
            if isinstance(value, list):
                for e in value:
                    ComboBoxExpandable.append_element(e, menu)
            elif isinstance(value, dict):
                for k, v in value.items():
                    ComboBoxExpandable.append_element(v, menu.addMenu(k))
            else:
                menu.addAction(value)
    
    
    class Widget(QtGui.QWidget):
        def __init__(self, parent=None):
            super(Widget, self).__init__(parent)
    
            combo = ComboBoxExpandable()
            combo.setData(data)
    
            result_label = QtGui.QLabel()
    
            combo.currentTextChanged.connect(result_label.setText)
            combo.pathChanged.connect(print)
    
            lay = QtGui.QFormLayout(self)
            lay.addRow("Select: ", combo)
            lay.addRow("Result: ", result_label)
    
    
    if __name__ == '__main__':
        import sys
    
        app = QtGui.QApplication(sys.argv)
        w = Widget()
        w.show()
        sys.exit(app.exec_())
    

    PyQt5:

    from PyQt5 import QtCore, QtWidgets
    
    data =[{
            "Courses": ["Math", "Science", "English"]
        },
        {
            "Cars": ["Ford", "BMW", "Mercedes"]
        }
    ]
    
    class ComboBoxExpandable(QtWidgets.QPushButton):
        currentTextChanged = QtCore.pyqtSignal(str)
        pathChanged = QtCore.pyqtSignal(list)
    
        def setData(self, value):
            menu = QtWidgets.QMenu(self)
            self.setMenu(menu)
            self.append_element(value, menu)
            menu.triggered.connect(self.on_triggered)
    
        @QtCore.pyqtSlot(QtWidgets.QAction)
        def on_triggered(self, action):
            self.setText(action.text())
            path = [action.text()] 
            w = action.parentWidget()
            while w.parentWidget() and isinstance(w.parentWidget(), QtWidgets.QMenu):
                path.insert(0, w.title())
                w = w.parentWidget()
            self.pathChanged.emit(path)
            self.currentTextChanged.emit(self.text())
    
        @staticmethod
        def append_element(value, menu):
            if isinstance(value, list):
                for e in value:
                    ComboBoxExpandable.append_element(e, menu)
            elif isinstance(value, dict):
                for k, v in value.items():
                    ComboBoxExpandable.append_element(v, menu.addMenu(k))
            else:
                menu.addAction(value)
    
    
    class Widget(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(Widget, self).__init__(parent)
    
            combo = ComboBoxExpandable()
            combo.setData(data)
    
            result_label = QtWidgets.QLabel()
    
            combo.currentTextChanged.connect(result_label.setText)
            combo.pathChanged.connect(print)
    
            lay = QtWidgets.QFormLayout(self)
            lay.addRow("Select: ", combo)
            lay.addRow("Result: ", result_label)
    
    
    if __name__ == '__main__':
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
        w = Widget()
        w.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 感谢您的回答。我怎样才能使它适用于 PyQt4?
    • @MS。您必须在问题中用标签指明版本。现在更新我的答案,现在试试。如果我的回答对您有帮助,请不要忘记将其标记为正确,如果您不知道该怎么做,请查看tour,这是最好的感谢方式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-13
    • 1970-01-01
    • 1970-01-01
    • 2019-03-19
    相关资源
    最近更新 更多