0

I can find some examples of how to use standard model with standard view.

http://doc.qt.io/qt-5/modelview.html

http://doc.qt.io/qt-5/qtwidgets-itemviews-simplewidgetmapper-example.html

but I just can not find ONE example of how to use QAbstractModel make my own model and to use it on my own view/widget.

After I update the model the stand view will update but not my own view.run result

Full code:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from  PyQt5.QtWidgets import (QWidget, QLabel, QDataWidgetMapper,
                              QLineEdit, QApplication, QGridLayout)
from PyQt5.QtCore import QAbstractListModel, Qt
from PyQt5.QtWidgets import QListView


class Window(QWidget):
    def __init__(self, model, parent=None):
        super(Window, self).__init__(parent)

        self.model = model

        # Set up the widgets.
        nameLabel = QLabel("Na&me:")
        nameEdit = QLineEdit()

        # Set up the mapper.
        self.mapper = QDataWidgetMapper(self)
        self.mapper.setModel(self.model)
        self.mapper.addMapping(nameEdit, 0)

        layout = QGridLayout()
        layout.addWidget(nameLabel, 0, 0, 1, 1)
        layout.addWidget(nameEdit, 0, 1, 1, 1)
        self.setLayout(layout)

        self.mapper.toFirst()


class MyModel(QAbstractListModel):
    def __init__(self, status=[], parent=None):
        super().__init__(parent)
        self.status = status

    def rowCount(self, index_parent=None, *args, **kwargs):
        return len(self.status)

    def data(self, index, role=Qt.DisplayRole, parent=None):
        if not index.isValid():
            return None
        row = index.row()
        if row == 0:
            print(index)
            if role == Qt.DisplayRole:
                return self.status[row]
            elif role == Qt.EditRole:  # if it's editing mode, return value for editing

                return self.status[row]

    def flags(self, index):
        return Qt.ItemIsEnabled | Qt.ItemIsEditable

    def setData(self, index, value='', role=Qt.EditRole):
        row = index.row()

        if role == Qt.EditRole:
            self.status[row] = value
            self.dataChanged.emit(index, index)  # inform the other view to request new data
            return True
        else:
            return False


if __name__ == '__main__':
    import sys

    app = QApplication(sys.argv)

    myModel_on_mywindow = MyModel([1, 2, 3])
    mywindow = Window(myModel_on_mywindow)
    mywindow.setWindowTitle('myModel_on_mywindow')
    mywindow.show()
    myModel_on_mywindow.status[0] = 2

    myModel_on_qlistview = MyModel([1, 2, 3])
    qlistview = QListView()
    qlistview.show()
    qlistview.setModel(myModel_on_qlistview)
    qlistview.setWindowTitle('myModel_on_qlistview')

    myModel_on_qlistview.status[0] = 2

    sys.exit(app.exec_())
9
  • What about Model Subclassing Reference and QAbstractItemModel ? Commented Jul 4, 2015 at 15:01
  • @Miki Thanks. I know how to make a customised model. but I do not know how to use it on my widget. Commented Jul 6, 2015 at 2:38
  • How about now? @ekhumoro Commented Jul 6, 2015 at 2:57
  • @Miki Can't I use QDataWidgetMapper like this: doc.qt.io/qt-5/… Commented Jul 6, 2015 at 10:30
  • @Miki If I use QListView I will need a lot of them, and a lot of models Commented Jul 6, 2015 at 10:33

1 Answer 1

5

Your custom model needs to override some functions of the abstract model, depending on which one you subclass. This is a small example for subclassing the QAbstractListModel. You can read more about this in the Qt documentation: QAbstractListModel Details

class MyModel(QAbstractListModel):
    def __init__(parent=None):
        QAbstractListModel.__init__(parent)
        self.content = []  # holds the data, you want to present

    def rowCount(index):
        return len(self.content)
    # This defines what the view should present at given index
    def data(index, role):
        if index.isValid() and role == Qt.DisplayRole):
            dataElement = self.content[index.row()]
            if index.colum() == 0:
                return dataElement.someBoolField
            if index.colum() == 1:
                return dataElement.someIntField
            # ...
        }
        return QVariant()  # this is like returning nothing
    }
    # If your items should be editable. Automatically called, when user changes the item.
    def setData(index, value, role):
        if index.isValid():
            dataElement = self.content[index.row()].get()
            if index.column() == 0:
                return dataElement.tryToSetBoolField(value.toBool())
            if index.column() == 1:
                return dataElement.tryToSetIntField(value.toInt())
            # ...
        }
        return True
    }
};

# connecting your view with your model
model = MyModel()
myView = QTreeView()  # or something else
myView.setModel(model)

EDIT

To update your view when using a custom Model in combination with a QDataMapper, call setCurrentIndex(changedIndex) or its wrappers after changing the model, like so in your case:

myModel_on_mywindow.status[0] = 2
myModel.mapper.toFirst()

The Qt documentation on QDataMapper mentions this in the detailed description:

The navigational functions toFirst(), toNext(), toPrevious(), toLast() and setCurrentIndex() can be used to navigate in the model and update the widgets with contents from the model.

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for your answer. I have done this and it works. The problem here is how to apply it to my widget, like this:class BicMainWindow(QWidget, Ui_Form):
Sorry for the delayed answer. I edited my answer to solve your problem. Just call setCurrentIndex() or its wrappers after changing your model.
@x squared Thank you very much for your answer. I have edited my question. I am sorry it's not very clear at beginning. I don't know should I ask a new question or still use this one. You can run my code you will find the problem.
I've seen the addition and added information at the end of my answer. Did that not solve your updating problem?
@x squared It's strange. It did solve my problem. Why? Will it create another group of data?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.