2014-12-21 5 views
0

Код ниже создает QTableView, управляемый self.myModel (QAbstractTableModel). «Показать все» self.checkBox связан с методом self.myModel.cbChanged().Как обновить QTableView, когда он управляется моделью

enter image description here

Вопрос: Как изменить этот код, так что «QTableView» получает обновляется, как только флажок?

Цель: когда флажок установлен, мы хотим, чтобы отображались нечетные номера. И четные номера будут скрыты. Если флажок выключен (не отмечен), мы хотим, чтобы отображались четные номера. Все нечетные номера скрыты.

import sys, os 
from PyQt4 import QtCore, QtGui 
app=QtGui.QApplication(sys.argv) 

class TableModel(QtCore.QAbstractTableModel): 
    def __init__(self): 
     QtCore.QAbstractTableModel.__init__(self)  

     self.items=['One','Two','Three','Four','Five','Six','Seven'] 
     self.cb_status=True 

    def rowCount(self, parent=QtCore.QModelIndex()): 
     return len(self.items) 
    def columnCount(self, index=QtCore.QModelIndex()): 
     return 1 

    def data(self, index, role): 
     if not index.isValid() or not (0<=index.row()<len(self.items)): 
      return QtCore.QVariant() 

     item=str(self.items[index.row()]) 

     if role==QtCore.Qt.DisplayRole and self.cb_status: 
      return item 
     else: 
      return QtCore.QVariant() 

    def cbChanged(self, arg=None): 
     self.cb_status=arg 

class Window(QtGui.QWidget): 
    def __init__(self): 
     super(Window, self).__init__() 
     mainLayout=QtGui.QHBoxLayout() 
     self.setLayout(mainLayout) 

     self.viewA=QtGui.QTableView() 
     self.viewA.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch) 

     self.myModel=TableModel() 
     self.viewA.setModel(self.myModel) 

     self.checkBox=QtGui.QCheckBox("Show All") 
     self.checkBox.stateChanged.connect(self.myModel.cbChanged) 
     self.checkBox.setChecked(self.myModel.cb_status) 

     mainLayout.addWidget(self.viewA) 
     mainLayout.addWidget(self.checkBox) 
     self.show() 

view=Window() 
sys.exit(app.exec_()) 
+0

Установить пустую модель в одном корпусе и модели с данными в другом корпусе? Просмотр будет обновляться автоматически. – Chernobyl

+0

Отправьте пример – alphanumeric

+0

Присвоение пустой «манекена» модели ВЕРОЯТНО работает в ситуации, когда флажок используется для включения и выключения элементов. Но если предположим, что мы хотим использовать флажок, чтобы переключаться между нечетными и четными номерами элементов, пустой подход модели не будет делать трюк ... – alphanumeric

ответ

4

С этой целью вы можете использовать класс QSortFilterProxyModel. Таким образом, мы не вмешиваемся в структуру фактической исходной модели или ее данные. Мы просто сопоставляем основной источник с этой прокси-моделью, которая используется для отображения фильтрованных/отсортированных данных. Мы можем повлиять на данные в прокси-модели, как нам заблагорассудится, без риска вмешательства в исходную модель.

Вот исходный код изменен, чтобы использовать эту функцию:

import sys, os 
from PyQt4 import QtCore, QtGui 
app=QtGui.QApplication(sys.argv) 

class TableModel(QtCore.QAbstractTableModel): 
    def __init__(self): 
     QtCore.QAbstractTableModel.__init__(self) 
     self.items=['One','Two','Three','Four','Five','Six','Seven'] 

    def rowCount(self, parent=QtCore.QModelIndex()): 
     return len(self.items) 
    def columnCount(self, index=QtCore.QModelIndex()): 
     return 1 

    def data(self, index, role): 
     if not index.isValid() or not (0<=index.row()<len(self.items)): 
      return QtCore.QVariant() 

     item=str(self.items[index.row()]) 

     if role==QtCore.Qt.DisplayRole: 
      return item 
     else: 
      return QtCore.QVariant() 


class MySortFilterProxyModel(QtGui.QSortFilterProxyModel): 
    def __init__(self): 
     super(MySortFilterProxyModel, self).__init__() 
     self.cb_status=True 

    def cbChanged(self, arg=None): 
     self.cb_status=arg 
     print self.cb_status 
     self.invalidateFilter() 

    def filterAcceptsRow(self, sourceRow, sourceParent): 
     print_when_odd_flag = self.cb_status 
     is_odd = True 
     index = self.sourceModel().index(sourceRow, 0, sourceParent) 
     print "My Row Data: %s" % self.sourceModel().data(index, role=QtCore.Qt.DisplayRole) 

     if (sourceRow + 1) % 2 == 0: 
      is_odd = False 

     if print_when_odd_flag: 
      if is_odd: 
       return True 
      else: 
       return False 
     else: 
      if not is_odd: 
       return True 
      else: 
       return False 


class Window(QtGui.QWidget): 
    def __init__(self): 
     super(Window, self).__init__() 
     mainLayout=QtGui.QHBoxLayout() 
     self.setLayout(mainLayout) 

     self.viewA=QtGui.QTableView() 
     self.viewA.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch) 

     self.myModel=TableModel() 

     self.sortModel = MySortFilterProxyModel() 
     self.sortModel.setSourceModel(self.myModel) 

     self.viewA.setModel(self.sortModel) 

     self.checkBox=QtGui.QCheckBox("Show All") 
     self.checkBox.stateChanged.connect(self.sortModel.cbChanged) 
     self.checkBox.setChecked(self.sortModel.cb_status) 

     mainLayout.addWidget(self.viewA) 
     mainLayout.addWidget(self.checkBox) 
     self.show() 

view=Window() 
sys.exit(app.exec_()) 

Как вы можете видеть, я удалил все соединения от интерфейса и основной исходной модели. Основная модель источника не заботится о том, установлен флажок или нет. Это держит его развязанным. Это чище. Теперь прокси-модель получила эту ответственность. filterAcceptsRow() делает основной тяжелый подъем отображения правой строки на основании того, является ли индекс указанной строки нечетным или даже основанным на статусе флажка.

Я добавил к нему несколько утверждений печати, на всякий случай, если вы хотите изменить логику на основе данных, а не индекса.

Проверьте документы на QSortFilterProxyModel и некоторые examples here.

Надеюсь, это было полезно.

+0

Спасибо за разъяснение! – alphanumeric

+0

Добро пожаловать, @Sputnix. – kartikg3