2015-07-04 2 views
0

Я могу найти несколько примеров того, как использовать стандартную модель со стандартным представлением.Как использовать QDataWidgetMapper в Qt или PyQt?

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

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

, но я просто не могу найти один пример того, как использовать QAbstractModel сделать мои собственные model и использовать его на моей view/widget.

После обновления модели просмотр стенда будет обновляться, но не мой собственный вид. run result

Полный код:

#!/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_()) 
+0

насчет [собственных моделей] (http://doc.qt.io/qt-5/model-view-programming.html#model-subclassing-reference) и [QAbstractItemModel] (HTTP: // doc.qt.io/qt-5/qabstractitemmodel.html)? – Miki

+0

@Miki Спасибо. Я знаю, как создать индивидуальную модель. но я не знаю, как использовать его на моем виджете. –

+0

Как насчет сейчас? @ekhumoro –

ответ

3

Ваш заказ модель требует, чтобы переопределить некоторые функции абстрактной модели, в зависимости от того, какой вы подклассы. Это небольшой пример для подкласса QAbstractListModel. Вы можете прочитать об этом в документации Qt: 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

Чтобы обновить вид при использовании пользовательской модели в сочетании с QDataMapper, вызовите setCurrentIndex (changedIndex) или его оболочки после изменение модели, как и в вашем случае:

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

документация Qt на QDataMapper упоминает об этом в подробном описании:

Навигационные функции toFirst(), toNext(), toPrevious(), toLast() и setCurrentIndex() могут быть использованы для навигации в модели и обновления виджетов с содержанием от модели.

+0

Спасибо за ваш ответ. Я сделал это, и он работает. Проблема заключается в том, как применить его к моему виджету, например: class BicMainWindow (QWidget, Ui_Form): –

+0

Извините за отложенный ответ. Я отредактировал свой ответ, чтобы решить вашу проблему. Просто позвоните 'setCurrentIndex()' или его обертки после изменения вашей модели. –

+0

@x squared Большое спасибо за ваш ответ. Я отредактировал мой вопрос. Мне жаль, что с самого начала это не очень понятно. Я не знаю, должен ли я задать новый вопрос или по-прежнему использовать этот. Вы можете запустить мой код, вы найдете проблему. –

Смежные вопросы