2017-10-18 5 views
0

pyqt5のサブタイプがQAbstractListModelのPythonリストを挿入/編集しようとしています。このpythonリストは、modelプロパティーのListView要素のqmlに読み込まれています。 qmlにデータを表示する際に問題はありません。私がPythonリストに新しいデータを追加しようとすると問題が発生します。 QAbstractListModelをpythonとqmlで自動的に挿入/編集する方法は?

は私がこれまでにやっていることです:

main.py:

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

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

     self.model = model2.PersonModel() 
     self.rootContext().setContextProperty('PersonModel', self.model) 
     self.rootContext().setContextProperty('MainWindow', self) 
     self.setSource(QUrl('test2.qml')) 

myApp = QApplication(sys.argv) 
ui = MainWindow() 
ui.show() 
sys.exit(myApp.exec_()) 

model2.py

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

class PersonModel(QAbstractListModel): 

    Name = Qt.UserRole + 1 
    Age = Qt.UserRole + 2 

    personChanged = pyqtSignal() 

    def __init__(self, parent=None): 
     super().__init__(parent) 
     self.persons = [ 
      {'name': 'jon', 'age': 20}, 
      {'name': 'jane', 'age': 25} 
     ] 

    def data(self, QModelIndex, role): 
     row = QModelIndex.row() 
     if role == self.Name: 
      return self.persons[row]["name"] 
     if role == self.Age: 
      return self.persons[row]["age"] 

    def rowCount(self, parent=None): 
     return len(self.persons) 

    def roleNames(self): 
     return { 
      Qt.UserRole + 1: b'name', 
      Qt.UserRole + 2: b'age' 
     } 

    @pyqtSlot() 
    def addData(self): 
     self.beginResetModel() 
     self.persons = self.persons.append({'name': 'peter', 'age': 22}) 
     self.endResetModel() 
     print(self.persons) 

    @pyqtSlot() 
    def editData(self): 
     print(self.model.persons) 

test2.qml:

import QtQuick 2.6 
import QtQuick.Controls 2.2 

Rectangle { 
    anchors.fill: parent 
    color: "lightgrey" 

    ListView { 
     id: listExample 
     anchors.fill: parent 
     model: PersonModel 
     delegate: Text { 
      text: name + " " + age 
     } 
    } 

    Button { 
     width: 50 
     height: 25 
     anchors.bottom: parent.bottom 
     text: "add" 
     onClicked: { 
      console.log("qml adding") 
      PersonModel.addData() 
     } 
    } 

    . 
    . 
    . 
} 

私がadd buをクリックするとエラーが発生するmodel2.pyでaddDataメソッドを呼び出すtton。エラーはrowCountにあり、エラーメッセージにはTypeError: object of type 'NoneType' has no len()と表示されます。変更を発行するか、いくつかのインデックスとロールの値を渡す必要があるので、qmlは新/古いものが分かり、それに応じて変更を反映するだけですか?

どのような形式のガイダンスも大変ありがとうございます。

答えて

0

あなたが得るエラーは、次のコード行によって引き起こされる:それは

をself.personsするNoneを代入することを意図したように、追記機能は、何も返さないので、それが原因で発生し

self.persons = self.persons.append({'name': 'peter', 'age': 22}) 

新しいデータを挿入するには、beginInsertRows()endInsertRows()に連絡して、変更をビューに通知する必要があります。

def data(self, index, role=Qt.DisplayRole): 

をrowCount方法と同じ::私が実装した

def rowCount(self, parent=QModelIndex()): 

それは次の形式を持っている必要があります。すなわち

データ方法は、マニュアルに示されたものと同一である必要がありますaddPerson、editPerson、deletePersonの各メソッドは、リストからデータを追加、編集、削除します。また、それをテストできるように.qmlに必要な項目を追加しました。

model2.py

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

class PersonModel(QAbstractListModel): 

    NameRole = Qt.UserRole + 1 
    AgeRole = Qt.UserRole + 2 

    personChanged = pyqtSignal() 

    def __init__(self, parent=None): 
     super().__init__(parent) 
     self.persons = [ 
      {'name': 'jon', 'age': 20}, 
      {'name': 'jane', 'age': 25} 
     ] 

    def data(self, index, role=Qt.DisplayRole): 
     row = index.row() 
     if role == PersonModel.NameRole: 
      return self.persons[row]["name"] 
     if role == PersonModel.AgeRole: 
      return self.persons[row]["age"] 

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

    def roleNames(self): 
     return { 
      PersonModel.NameRole: b'name', 
      PersonModel.AgeRole: b'age' 
     } 

    @pyqtSlot(str, int) 
    def addPerson(self, name, age): 
     self.beginInsertRows(QModelIndex(), self.rowCount(), self.rowCount()) 
     self.persons.append({'name': name, 'age': age}) 
     self.endInsertRows() 

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

    @pyqtSlot(int) 
    def deletePerson(self, row): 
     self.beginRemoveColumns(QModelIndex(), row, row) 
     del self.persons[row] 
     self.endRemoveRows() 

test2.qml

import QtQuick 2.6 
import QtQuick.Controls 2.2 

Rectangle { 
    anchors.fill: parent 
    color: "lightgrey" 

    ListView { 
     id: listExample 
     anchors.fill: parent 
     model: PersonModel 
     delegate: 
      Item { 
      width: 200 
      height: 60 
      Row { 
       Text { 
        width: 60 
        text: name + " " + age 
        horizontalAlignment: Text.AlignHCenter 
        anchors.verticalCenter: parent.verticalCenter 
       } 
       Button{ 
        width: 20 
        text: "+" 
        onClicked: PersonModel.editPerson(index, name, age+1) 
       } 
       Button{ 
        width: 20 
        text: "-" 
        onClicked: PersonModel.editPerson(index, name, age-1) 
       } 
       Button{ 
        width: 20 
        text: "X" 
        onClicked: PersonModel.deletePerson(index) 
       } 
      } 
     } 
    } 

    Button { 
     width: 50 
     height: 25 
     anchors.bottom: parent.bottom 
     anchors.right: parent.right 
     text: "add" 
     onClicked: { 
      console.log("qml adding") 
      PersonModel.addPerson("luis", 22) 
     } 
    } 
} 

編集:

の.py

@pyqtSlot(int, str, int) 
def insertPerson(self, row, name, age): 
    self.beginInsertRows(QModelIndex(), row, row) 
    self.persons.insert(row, {'name': name, 'age': age}) 
    self.endInsertRows() 

。qml

PersonModel.insertPerson(2, "luis", 1111) 
+0

hey eyllanesc! pyqt5とqmlについて私の質問に返信してくれてありがとう!私は 'beginInsertRows'メソッドの2番目と3番目のパラメータで遊んでいましたが、jonとjaneの間に新しく追加されたデータを挿入することはできません。それはどうすればいいのですか?ああ、ところで、pyqt5とqmlのリソースを知っていますか? – eugeneoei

+0

@eugeneoeiさて、しばらくすると、私は挿入メソッドを作成します。 2番目の点には公式のドキュメントはありません。実際、PyQtの公式ドキュメントはQtのドキュメントを指しています。したがって、C++の最小限の知識があれば分かります。私の答えを正しいものとしてマークすることを忘れないでください。 – eyllanesc

+0

cool!私は今どこが間違っていたのか知​​っています。リスト内の特定の位置に辞書を追加しようとしていました。それは間違いなく動作しません。まだPythonには非常に新しいです。少なくとも私は今知っている。おかげでeyllanesc! – eugeneoei

関連する問題