【问题标题】:How to select row in listview如何在列表视图中选择行
【发布时间】:2019-12-22 16:42:02
【问题描述】:

我在网上搜索,但我没有找到如何在列表视图中选择一行,使用 python 在 qml 文件中创建。我测试但每次我都有错误。 我刚开始qml,也许基础不好。所以我的问题是,使用我的代码,可以访问我的 ListView 吗?如果是,我如何在启动应用程序中选择第二项(例如)?

当我这样做时:

print(win.findChild(QObject, "listview22").setCurrentIndex(2)))

我有这条消息

AttributeError: 'QQuickItem' object has no attribute 'setCurrentIndex'

但是 listview22 是一个列表视图而不是一个项目。

感谢您的帮助。

PS : 我刚开始 qml 所以如果我的脚本不好告诉我然后我可以学习好的编程

main.qml

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1

ApplicationWindow {
    title: qsTr("WoodMan Training")

    width: 1000
    height: 700

    visible: true

    GridLayout {
        id: grid
        anchors.fill: parent
        columns: 3
        anchors.margins: 0
        columnSpacing: 0

        ColumnLayout {
            Layout.columnSpan: 1
            Layout.row: 2
            Layout.column: 0
            Layout.fillWidth: true
            Layout.fillHeight: true

            Layout.margins: 10

            Layout.maximumWidth: 250

                // ---
            RowLayout{
            Main_ListView{objectName: "lstGroupe"; id:lstGroupe; pyModel: ModelGroupe; pyClass: ModelGroupe}
            }       

            Item {Layout.fillWidth: true; Layout.fillHeight: true}

        }
     }  
}

Main_ListView.qml

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2

Rectangle {
    property var pyClass: 0
    property var pyModel: 0


    border.color: "red"
    Layout.fillWidth: true
    height:150


    ListView {
        anchors.topMargin: 10
        anchors.bottomMargin: 10
        anchors.leftMargin: 10
        anchors.fill: parent

        id: listview22
        objectName: "listview22"

        model: pyModel
        clip: true                                                      // --- Empeche la surbrillance de sortir du cadre

        delegate: Component {
            Item {
                width: 200
                height: 20

                property int item_id: iid

                Row {
                    Text {
                        anchors.verticalCenter: parent.verticalCenter

                        width: 60
                        text:  "  " + libelle
                    }
                }

                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        listview22.currentIndex = index
                        pyClass.onClickItem(item_id)                        
                    }
                }               

            }
        }
        highlight: Rectangle {color: '#CDCDCD'}
        focus: true     
    }

    Button {
        anchors.bottom: parent.bottom              
        anchors.right: parent.right
        anchors.rightMargin: 5
        anchors.bottomMargin: 5

        width: 28
        height: 25

        iconSource: "ico/math-add-icon.png"

        onClicked: {
            //console.log("qml adding")
            pyClass.onClickInsert(22, "aluis")
        }
    }

}



main.py

from PyQt5.QtCore import QAbstractListModel, Qt, pyqtSignal, pyqtSlot, QModelIndex    

import sys
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQuick import QQuickView

from PyQt5.QtGui import *#QGuiApplication, QColor, QStandardItemModel, QStandardItem
from PyQt5.QtQml import *#QQmlApplicationEngine, QQmlComponent
from PyQt5.QtCore import *#QUrl, Qt, QCoreApplication, QAbstractListModel, QModelIndex, QTimer, qsrand, qrand, QTime, QObject
from PyQt5.QtQuick import *#QQuickItem



class gGroupe(QAbstractListModel):


    iid = Qt.UserRole + 1
    libelle = Qt.UserRole + 2

    data_change = pyqtSignal()

    def __init__(self, parent=None):

        super().__init__(parent)

        self.liste = []
        self.insert_list()

        self.liste2 = {}

        self.createIndex(0,0,125)
        self.sort(1, order = Qt.DescendingOrder)


    # ------------------------------------------------------------------

    def roleNames(self):
        return {
            gGroupe.iid: b'iid',
            gGroupe.libelle: b'libelle',
        }

    def data(self, index, role=Qt.DisplayRole):
        row = index.row()
        if role == gGroupe.iid:
            return self.liste[row]["iid"]
        if role == gGroupe.libelle:
            return self.liste[row]["libelle"]

    def rowCount(self, parent=QModelIndex()):
        return len(self.liste)

    # ------------------------------------------------------------------

    def insert_list(self):

        self.liste = [
            {'iid': 10, 'libelle': 'groupe10'},
            {'iid': 11, 'libelle': 'groupe11'},
            {'iid': 12, 'libelle': 'groupe12'},
        ]


    def delete(self, row):
        self.beginRemoveRows(QModelIndex(), row, row)
        del self.liste[row]
        self.endRemoveRows()  

    def delete_all(self):
        self.beginRemoveRows(QModelIndex(), 0, len(self.liste))
        del self.liste[row]
        self.endRemoveRows()  

    def select(self):
        pass

    @pyqtSlot(int, str)
    def onClickInsert(self, iid=10, libelle='toto'):

        self.beginInsertRows(QModelIndex(), self.rowCount(), self.rowCount())
        self.liste.append({'iid': iid, 'libelle': libelle})
        self.endInsertRows()

        return self.index(len(self.liste)-1)

    @pyqtSlot(int)
    def onClickItem(self, iid):
        print(iid)

    """
    @pyqtSlot(int, str, int)
    def editPerson(self, row, name, age):
        ix = self.index(row, 0)
        self.persons[row] = {'iid': 22, 'name': name, 'age': age}
        self.dataChanged.emit(ix, ix, self.roleNames())
    """


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

        self.g_groupe = gGroupe()
        engine.rootContext().setContextProperty('ModelGroupe', self.g_groupe)

        engine.load('main.qml')
        win = engine.rootObjects()[0]

        #win.findChild(QObject, "txtLibelle").setProperty("text", 'toto')

        print(win.findChild(QObject, "listview22").setCurrentIndex(2))

        a = win.findChild(QObject, "PersonModel")#.removeRows( 0, model.rowCount() )


if __name__ == "__main__":
    app = QApplication(sys.argv)
    engine = QQmlApplicationEngine()
    # Création d'un objet QQmlContext pour communiquer avec le code QML
    #ctx = engine.rootContext()
    py_mainapp = MainWindow()
    sys.exit(app.exec())

【问题讨论】:

    标签: python listview pyqt qml pyqt5


    【解决方案1】:

    您有以下错误:

    • 您不应该将 QML 对象导出到 python,因为它会给您带来许多错误,例如您遇到的错误,甚至更严重的错误,这是在 C++ 中推荐的。

    • 在 C++ 中尝试使用 findChild (QObject, "listview22") 获取 ListView 时,只会获得一个 QObject,但 python 会尝试推断类型,因此它限制了 Qt 的公共 API ,在您的 ListView 中它不是 QListView,并且它的类型在 Python 或 C++ 中不存在,因为它是私有 API 的一部分,因此附近的类是 QQuickItem,因为 ListView 继承自该类。

    建议创建一个QObject并添加映射逻辑并导出到QML的qproperties,因此如果您在python中修改QObject,它将在QML中修改它。

    ma​​in.py

    from PyQt5.QtCore import (
        pyqtProperty,
        pyqtSignal,
        pyqtSlot,
        QAbstractListModel,
        QModelIndex,
        QObject,
        Qt,
        QTimer,
    )
    from PyQt5.QtGui import QGuiApplication
    from PyQt5.QtQml import QQmlApplicationEngine
    
    
    class gGroupe(QAbstractListModel):
    
        iid = Qt.UserRole + 1
        libelle = Qt.UserRole + 2
    
        data_change = pyqtSignal()
    
        def __init__(self, parent=None):
            super().__init__(parent)
    
            self.liste = []
            self.insert_list()
    
            self.sort(0, order=Qt.DescendingOrder)
    
        def roleNames(self):
            return {gGroupe.iid: b"iid", gGroupe.libelle: b"libelle"}
    
        def data(self, index, role=Qt.DisplayRole):
            row = index.row()
            if role == gGroupe.iid:
                return self.liste[row]["iid"]
            if role == gGroupe.libelle:
                return self.liste[row]["libelle"]
    
        def rowCount(self, parent=QModelIndex()):
            return len(self.liste)
    
        # ------------------------------------------------------------------
    
        def insert_list(self):
            self.beginResetModel()
            self.liste = [
                {"iid": 10, "libelle": "groupe10"},
                {"iid": 11, "libelle": "groupe11"},
                {"iid": 12, "libelle": "groupe12"},
            ]
            self.endResetModel()
    
        def delete(self, row):
            self.beginRemoveRows(QModelIndex(), row, row)
            del self.liste[row]
            self.endRemoveRows()
    
        def delete_all(self):
            self.beginRemoveRows(QModelIndex(), 0, len(self.liste))
            del self.liste[row]
            self.endRemoveRows()
    
        def select(self):
            pass
    
        @pyqtSlot(int, str)
        def insert(self, iid=10, libelle="toto"):
            self.beginInsertRows(QModelIndex(), self.rowCount(), self.rowCount())
            self.liste.append({"iid": iid, "libelle": libelle})
            self.endInsertRows()
    
        @pyqtSlot(int)
        def onClickItem(self, iid):
            print(iid)
    
    
    class MainWindow(QObject):
        currentIndexChanged = pyqtSignal(int)
    
        def __init__(self, parent=None):
            super().__init__(parent)
            self._g_groupe = gGroupe(self)
            self._current_index = 0
    
        @pyqtProperty(QObject, constant=True)
        def g_groups(self):
            return self._g_groupe
    
        @pyqtProperty(int, notify=currentIndexChanged)
        def currentIndex(self):
            return self._current_index
    
        @currentIndex.setter
        def currentIndex(self, index):
            if self._current_index == index:
                return
            self._current_index = index
            self.currentIndexChanged.emit(index)
    
    if __name__ == "__main__":
        import sys
    
        app = QGuiApplication(sys.argv)
        engine = QQmlApplicationEngine()
        main_window = MainWindow()
        engine.rootContext().setContextProperty("main_window", main_window)
        engine.load("main.qml")
        if not engine.rootObjects():
            sys.exit(app.exec_())
    
        main_window.currentIndex = 2
    
        sys.exit(app.exec())
    

    ma​​in.qml

    import QtQuick 2.4
    import QtQuick.Controls 1.3
    import QtQuick.Layouts 1.1
    
    ApplicationWindow {
        title: qsTr("WoodMan Training")
    
        width: 1000
        height: 700
    
        visible: true
    
        Connections{
            target: main_window
            onCurrentIndexChanged: lstGroupe.currentIndex = main_window.currentIndex
        }
    
        GridLayout {
            id: grid
            anchors.fill: parent
            columns: 3
            anchors.margins: 0
            columnSpacing: 0
    
            ColumnLayout {
                Layout.columnSpan: 1
                Layout.row: 2
                Layout.column: 0
                Layout.fillWidth: true
                Layout.fillHeight: true
    
                Layout.margins: 10
    
                Layout.maximumWidth: 250
    
                    // ---
                RowLayout{
                    Main_ListView{
                        id:lstGroupe; 
                        model: main_window.g_groups
                    }
                }       
    
                Item {
                    Layout.fillWidth: true
                    Layout.fillHeight: true
                }
            }
        }  
    }
    

    Main_ListView.qml

    import QtQuick 2.4
    import QtQuick.Controls 1.3
    import QtQuick.Layouts 1.1
    import QtQuick.Window 2.2
    
    Rectangle {
        id: root
        property alias model: listview22.model
        property alias currentIndex: listview22.currentIndex
    
        border.color: "red"
        Layout.fillWidth: true
        height:150
    
        ListView {
            id: listview22
            model: root.model
            anchors.topMargin: 10
            anchors.bottomMargin: 10
            anchors.leftMargin: 10
            anchors.fill: parent
            clip: true
    
            delegate: Component {
                Item {
                    width: 200
                    height: 20
                    property int item_id: iid
                    Row {
                        Text {
                            anchors.verticalCenter: parent.verticalCenter
                            width: 60
                            text:  "  " + libelle
                        }
                    }
                    MouseArea {
                        anchors.fill: parent
                        onClicked: {
                            listview22.currentIndex = index
                            listview22.model.onClickItem(item_id)                        
                        }
                    }               
                }
            }
            highlight: Rectangle {color: '#CDCDCD'}
            focus: true     
        }
        Button {
            anchors.bottom: parent.bottom              
            anchors.right: parent.right
            anchors.rightMargin: 5
            anchors.bottomMargin: 5
            width: 28
            height: 25
            iconSource: "ico/math-add-icon.png"
            onClicked: {
                listview22.model.insert(22, "aluis")
            }
        }
    }
    

    【讨论】:

    • 非常感谢...我开始更好地理解它是如何工作的
    • 真的很酷,你的代码很干净,非常清晰,我学习得很好,我想我理解了这些概念......还没有完全掌握,但随着时间的推移它会到来。再次感谢。
    • 简单但实用的示例,正​​是我所需要的,并且我可以使用 Python 快速掌握 QT 和 QML。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多