Как добавить элементы меню Dynami c из PyQt в QML Drawer - PullRequest
1 голос
/ 11 февраля 2020

В настоящее время у меня возникают некоторые проблемы с добавлением пунктов меню динамического c из PyQt в QAbstractListModel внутри QML Drawer.

В следующих ссылках можно найти соответствующие файлы QML, которые я использую: main.qml и NavigationDrawer.qml

hook.py:

class QDrawer(QQuickView):

    close_button_clicked = QtCore.pyqtSignal()
    error_triggered = QtCore.pyqtSignal()
    on_transparent_frame_clicked = QtCore.pyqtSignal()


    def __init__(self, parent=None, layout=None, drawerMenuEntriesList=[], callback=None):
        super().__init__()
        self.parent =  parent

        qmlRegisterType(QPythonBinding, "MyApplication", 1, 0, "QPythonBinding")

        # Formatting of the QDrawer
        self._format(QtGui.QColor(QtCore.Qt.transparent))
        self._source_qml_file("main.qml")

        self.setResizeMode(self.SizeRootObjectToView)

        self.engine().rootContext().setContextProperty("QDrawer", self)

        # Prevent from continuing if the QML file was not successfully sourced
        if not self.engine().rootContext():
            logger.error("No object could be loaded from sourced QML file and create a context out of it")
            self.error_detected()

        # Connections
        self.statusChanged.connect(self.on_statusChanged)

        self.transparent_frame = QWidget()
        eventFilter_transparent_frame = _Filter(self.transparent_frame)
        self.transparent_frame.installEventFilter(eventFilter_transparent_frame)
        eventFilter_transparent_frame.released.connect(self.transparent_frame_clicked)

        self._add_drawer_to_container_on_layout(layout)

        # the callback function is propagated up to the ui_controller 
        self.populate(drawerMenuEntriesList, callback)

        logger.debug(f"Drawer created")

    ...

    def populate(self, drawerMenuEntriesList, callback):
        menu = self._get_qml_component_by_objectname(QtCore.QAbstractListModel, "drawer_list")

        qpybinding = QPythonBinding()

        for entry in menuEntries:
            logger.debug(f"≡ [Drawer]: Adding '{entry}' to drawer model")
            qpybinding.addElement.emit(entry)

Полученный ящик выглядит следующим образом:

Displayed drawer menu


Идея состоит в том, чтобы заменить в меню выдвижного ящика записи «Фрагмент X» на любые пользовательские строковые записи, определяемые как « knifeMenuEntriesList"на заполнить () функция.

1 Ответ

0 голосов
/ 11 февраля 2020

Предоставление необходимого кредита сообщению "QML - Урок 019. Ящик навигации в Qt Qml Android" , который, кажется, использует OP для своего примера.

Если анализируется код QML, необходимо только создать модель из python (например, QStandardItemModel), экспортировать ее в QML с помощью setContextProperty и установить ее в ListView.

import sys

from PyQt5 import QtCore, QtGui, QtQuick


class QDrawer(QtQuick.QQuickView):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setResizeMode(self.SizeRootObjectToView)
        self.entry_model = QtGui.QStandardItemModel()
        self.rootContext().setContextProperty("entry_model", self.entry_model)
        self.setSource(QtCore.QUrl.fromLocalFile("main.qml"))

    def addEntry(self, entry):
        it = QtGui.QStandardItem(entry)
        self.entry_model.appendRow(it)


def main():
    app = QtGui.QGuiApplication(sys.argv)
    w = QDrawer()
    for i in range(10):
        w.addEntry("entry-{}".format(i))
    w.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

main.qml

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import QtQuick.Window 2.12

Rectangle {
    id: window
    width: 360
    height: 520
    color: "#00000000"
    readonly property int dpi: Screen.pixelDensity * 25.4
    function dp(x){ return (dpi < 120) ? x : x*(dpi/160); }

    // Application Bar
    Rectangle {
        id: menuRect
        anchors.top: parent.top
        anchors.left: parent.left
        anchors.right: parent.right
        height: dp(48)
        color: "#4cd964"

        // Icon-Hamburger
        Rectangle {
            anchors.top: parent.top
            anchors.bottom: parent.bottom
            anchors.left: parent.left

            width: dp(48)
            color: "#4cd964"

            Rectangle {
                anchors.top: parent.top
                anchors.topMargin: dp(16)
                anchors.left: parent.left
                anchors.leftMargin: dp(14)
                width: dp(20)
                height: dp(2)
            }

            Rectangle {
                anchors.top: parent.top
                anchors.topMargin: dp(23)
                anchors.left: parent.left
                anchors.leftMargin: dp(14)
                width: dp(20)
                height: dp(2)
            }

            Rectangle {
                anchors.top: parent.top
                anchors.topMargin: dp(30)
                anchors.left: parent.left
                anchors.leftMargin: dp(14)
                width: dp(20)
                height: dp(2)
            }

            MouseArea {
                anchors.fill: parent

                onClicked: {
                    nav.toggle()
                }
            }
        }

    }

    Label{
        id: label
        anchors.top: menuRect.bottom
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        horizontalAlignment: Text.AlignHCenter
        verticalAlignment: Text.AlignVCenter
    }

    NavigationDrawer {
        id: nav
        width: window.width * .75
        Rectangle {
            anchors.fill: parent
            color: "white"

            ListView {
                anchors.fill: parent

                delegate: Item {
                    height: dp(48)
                    anchors.left: parent.left
                    anchors.right: parent.right

                    Rectangle {
                        anchors.fill: parent
                        anchors.margins: dp(5)
                        color: "whitesmoke"

                        Text {
                            text: model.display
                            anchors.fill: parent
                            font.pixelSize: dp(20)

                            renderType: Text.NativeRendering
                            horizontalAlignment: Text.AlignHCenter
                            verticalAlignment: Text.AlignVCenter
                        }

                        MouseArea {
                            anchors.fill: parent
                            onClicked: {
                                label.text = index + " : " + model.display
                                nav.hide()
                            }
                        }
                    }
                }

                model: entry_model
            }
        }
    }
}

enter image description here

...