Breadcrumbs navigation using QToolBar and QListView

久未见 提交于 2020-01-15 09:48:27

问题


I have JSON data something like this

{"books":{
    "web":{
      "front-end":{
        "html":["the missing manual", "core html5 canvas"],
        "css":["css pocket reference", "css in depth"],
        "js":["you don't know js", "eloquent javascript"]
      },
      "back-end":{
        "php":["modern php", "php web services"],
        "python":["dive into python", "python for everybody", 
        "Think Python", "Effective Python", "Fluent Python"]
      }
    },
    "database":{
      "sql":{
        "mysql":["mysql in a nutshell", "mysql cookbook"],
        "postgresql":["postgresql up and running", "practical postgresql"]
      },
      "nosql":{
        "mongodb":["mongodb in action", "scaling mongodb"],
        "cassandra":["practical cassandra", "mastering cassandra"]
}}}}

Now I want to populate this data in QListView using QAbstractListModel with the QToolBar as breadcrumb navigation (QAction). QListView will update as user triggers key. So how can I implement this?


回答1:


The first thing is to convert the json into a model, in this case QStandardItemModel is used. Then we use that model in the QListView using setRootIndex() to indicate the items that will be displayed, on the other hand QActions are added to the QToolBar using the parent tree.

from PyQt5 import QtCore, QtGui, QtWidgets

data = {"books":{
    "web":{
      "front-end":{
        "html":["the missing manual", "core html5 canvas"],
        "css":["css pocket reference", "css in depth"],
        "js":["you don't know js", "eloquent javascript"]
      },
      "back-end":{
        "php":["modern php", "php web services"],
        "python":["dive into python", "python for everybody", 
        "Think Python", "Effective Python", "Fluent Python"]
      }
    },
    "database":{
      "sql":{
        "mysql":["mysql in a nutshell", "mysql cookbook"],
        "postgresql":["postgresql up and running", "practical postgresql"]
      },
      "nosql":{
        "mongodb":["mongodb in action", "scaling mongodb"],
        "cassandra":["practical cassandra", "mastering cassandra"]
}}}}

def dict_to_model(item, d):
    if isinstance(d, dict):
        for k, v in d.items():
            it = QtGui.QStandardItem(k)
            item.appendRow(it)
            dict_to_model(it, v)
    elif isinstance(d, list):
        for v in d:
            dict_to_model(item, v)
    else:
        item.appendRow(QtGui.QStandardItem(str(d)))

class Navigation(QtCore.QObject):
    clicked = QtCore.pyqtSignal(QtCore.QModelIndex)
    def __init__(self, json_data, parent=None):
        super(Navigation, self).__init__(parent)
        self.toolbar = QtWidgets.QToolBar()
        self.toolbar.actionTriggered.connect(self.on_actionTriggered)
        self.model =  QtGui.QStandardItemModel(self)
        dict_to_model(self.model.invisibleRootItem(), json_data)
        it = self.model.item(0, 0)
        ix = self.model.indexFromItem(it)
        root_action = self.toolbar.addAction(it.text())
        root_action.setData(QtCore.QPersistentModelIndex(ix))
        self.listview = QtWidgets.QListView()
        self.listview.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.listview.clicked.connect(self.on_clicked)
        self.listview.setModel(self.model)
        self.listview.setRootIndex(ix)

    @QtCore.pyqtSlot(QtCore.QModelIndex)
    def on_clicked(self, index):
        if not self.model.hasChildren(index):
            self.clicked.emit(index)
            return
        action = self.toolbar.addAction(index.data())
        action.setData(QtCore.QPersistentModelIndex(index))
        self.listview.setRootIndex(index)

    @QtCore.pyqtSlot(QtWidgets.QAction)
    def on_actionTriggered(self, action):
        ix = action.data()
        model = ix.model()
        self.listview.setRootIndex(QtCore.QModelIndex(ix))
        self.toolbar.clear()
        ixs = []
        while  ix.isValid():
            ixs.append(ix)
            ix = ix.parent()
        for ix in reversed(ixs):
            action = self.toolbar.addAction(ix.data())
            action.setData(ix)

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        navigation = Navigation(data, self)
        navigation.clicked.connect(self.on_clicked)

        tree_view = QtWidgets.QTreeView()
        tree_view.setModel(navigation.model)
        navigation.model.setHorizontalHeaderLabels(["Tree Example"])
        tree_view.expandAll()

        self.addToolBar(navigation.toolbar)

        widget = QtWidgets.QWidget()
        self.setCentralWidget(widget)
        lay = QtWidgets.QHBoxLayout(widget)
        lay.addWidget(navigation.listview)
        lay.addWidget(tree_view)

    @QtCore.pyqtSlot(QtCore.QModelIndex)
    def on_clicked(self, index):
        print(index.data())

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())


来源:https://stackoverflow.com/questions/53022651/breadcrumbs-navigation-using-qtoolbar-and-qlistview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!