【问题标题】:How to add dynamic menu entries from PyQt into a QML Drawer如何将 PyQt 中的动态菜单条目添加到 QML Drawer
【发布时间】:2020-05-27 01:00:41
【问题描述】:

我目前在将动态菜单条目从 PyQt 添加到 QML Drawer 内的 QAbstractListModel 时遇到了一些麻烦。

在以下链接中可以找到我正在使用的相应 QML 文件:main.qmlNavigationDrawer.qml

drawer.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)

生成的抽屉如下所示:


这个想法是用 populate() 函数中的“drawerMenuEntriesList”确定的任何自定义字符串条目替换抽屉菜单中的条目“Fragment X”。

【问题讨论】:

标签: python pyqt qml


【解决方案1】:

给予"QML - Lesson 019. Navigation Drawer in Qt Qml Android" 帖子必要的功劳,该帖子似乎以 OP 为例。

如果分析QML代码,只需从python创建模型(例如QStandardItemModel),用setContextProperty导出到QML并设置在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()

ma​​in.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
            }
        }
    }
}

【讨论】:

  • 非常感谢!你已经完全搞定了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-19
  • 2013-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多