2013-07-17 10 views
12

Chciałbym wyświetlić ramkę danych pandy w tabeli PyQt. Poczyniłem pewne postępy w tym zakresie, ale nie byłem w stanie prawidłowo wyprowadzić klasy modelu tabeli. Jakakolwiek pomoc w tej sprawie byłaby bardzo doceniana.PyQt - Implementacja QAbstractTableModel do wyświetlania w QTableView

** Uwaga pełny przykład kodu here **

walczę Wygenerowanie odpowiedniego QtCore.QAbstractTableModel klasy pochodnej. Kontynuując poprzednie pytanie dotyczące QItemDelegates, próbuję wygenerować model tabeli z Pandas DataFrame, aby wstawić prawdziwe dane. Mam działający kod przykładowy here, ale jeśli zamieniam mój TableModel na TableModel2 w klasie Widget (ln 152), nie mogę wyświetlić tabeli.

class TableModel2(QtCore.QAbstractTableModel): 
    def __init__(self, parent=None, *args): 
     super(TableModel2, self).__init__() 
     #QtCore.QAbstractTableModel.__init__(self, parent, *args) 
     self.datatable = None 
     self.headerdata = None 
     self.dataFrame = None 
     self.model = QtGui.QStandardItemModel(self) 

    def update(self, dataIn): 
     print 'Updating Model' 
     self.datatable = dataIn 
     print 'Datatable : {0}'.format(self.datatable) 
     headers = dataIn.columns.values 
     header_items = [ 
        str(field) 
        for field in headers 
     ] 
     self.headerdata = header_items 
     print 'Headers' 
     print self.headerdata 

     for i in range(len(dataIn.index.values)): 
      for j in range(len(dataIn.columns.values)): 
       #self.datatable.setItem(i,j,QtGui.QTableWidgetItem(str(df.iget_value(i, j)))) 
       self.model.setItem(i,j,QtGui.QStandardItem(str(dataIn.iget_value(i, j)))) 

    def rowCount(self, parent=QtCore.QModelIndex()): 
     return len(self.datatable.index) 

    def columnCount(self, parent=QtCore.QModelIndex()): 
     return len(self.datatable.columns.values) 

    def data(self, index, role=QtCore.Qt.DisplayRole): 
     if not index.isValid(): 
      return QtCore.QVariant() 
     elif role != QtCore.Qt.DisplayRole: 
      return QtCore.QVariant() 
     #return QtCore.QVariant(self.model.data(index)) 
      return QtCore.QVariant(self.model.data(index)) 

    def headerData(self, col, orientation, role): 
     if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole: 
      return QtCore.QVariant() 
     return QtCore.QVariant(self.headerdata[col]) 

    def setData(self, index, value, role=QtCore.Qt.DisplayRole): 
     print "setData", index.row(), index.column(), value 

    def flags(self, index): 
     if (index.column() == 0): 
      return QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled 
     else: 
      return QtCore.Qt.ItemIsEnabled 

Ja próbuje stworzyć model, a następnie dodać go do widoku, tak:

class Widget(QtGui.QWidget): 
    """ 
    A simple test widget to contain and own the model and table. 
    """ 
    def __init__(self, parent=None): 
     QtGui.QWidget.__init__(self, parent) 

     l=QtGui.QVBoxLayout(self) 
     cdf = self.get_data_frame() 
     self._tm=TableModel(self) 
     self._tm.update(cdf) 
     self._tv=TableView(self) 
     self._tv.setModel(self._tm) 
     for row in range(0, self._tm.rowCount()): 
      self._tv.openPersistentEditor(self._tm.index(row, 0)) 
     l.addWidget(self._tv) 

    def get_data_frame(self): 
     df = pd.DataFrame({'Name':['a','b','c','d'], 
     'First':[2.3,5.4,3.1,7.7], 'Last':[23.4,11.2,65.3,88.8], 'Class':[1,1,2,1], 'Valid':[True, True, True, False]}) 
     return df 

Dziękujemy za uwagę!

Uwaga: edycja 2 Dołączyłem QStandardItemModel do TableModel2. Usunięto również funkcję dataFrameToQtTable po komentarzu @ mata. Jest coraz bliżej, ale wciąż nie działa.

+0

Pandy jest przykładem tabeli Qt w repo . https://github.com/pydata/pandas/commits/master/pandas/sandbox/qtpandas.py –

Odpowiedz

10

OK Pomyślałem o tym z powyższą sugestią i pomocą z podręcznika Rapid GUI Summerfielda. Nie ma żadnego bazowego modelu, który istnieje w QAbstractTableModel. Tylko trzy funkcje muszą zostać nadpisane, a dane mogą być przechowywane w dowolnym formacie zdefiniowanym przez użytkownika, o ile są zwracane w wywołaniu danych.

Bardzo prosta implementacja może być:

class TableModel(QtCore.QAbstractTableModel): 
    def __init__(self, parent=None, *args): 
     super(TableModel, self).__init__() 
     self.datatable = None 

    def update(self, dataIn): 
     print 'Updating Model' 
     self.datatable = dataIn 
     print 'Datatable : {0}'.format(self.datatable) 

    def rowCount(self, parent=QtCore.QModelIndex()): 
     return len(self.datatable.index) 

    def columnCount(self, parent=QtCore.QModelIndex()): 
     return len(self.datatable.columns.values) 

    def data(self, index, role=QtCore.Qt.DisplayRole): 
     if role == QtCore.Qt.DisplayRole: 
      i = index.row() 
      j = index.column() 
      return '{0}'.format(self.datatable.iget_value(i, j)) 
     else: 
      return QtCore.QVariant() 

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

ta umożliwia wyświetlanie dowolnego kompatybilne ramki danych w widoku Qt.

I zostały zaktualizowane GIST nad here

To powinno Ci będzie szybko, jeśli trzeba także, aby to zrobić.

+0

Niestety nazwy kolumn i indeksów nie są wyświetlane? Będzie miło, jeśli możesz to naprawić. – working4coins

1

Jest to prawdopodobnie problem:

def rowCount(self, parent=QtCore.QModelIndex()): 
    if type(self.datatable) == pd.DataFrame: 
    ... 


def columnCount(self, parent=QtCore.QModelIndex()): 
    if (self.datatable) == pd.DataFrame: 
    ... 

tak ustawić datatable do QTableWidget w dataFrameToQtTable, więc to nie może być pd.DataFrame, wasze metody zawsze zwraca 0.

Bez typu sprawdź, natychmiast byś złapał problem. Czy naprawdę chcesz cicho zignorować wszystkie przypadki, w których twój typ się nie zgadza (lepiej pozwolić mu na zgłoszenie błędu, jeśli nie jest zgodny z tym samym interfejsem, którego się spodziewasz)? Typechecks to in most cases unnecessary.

+0

Tak, wiem, że to jest złe, ale to jest mój problem. Nie sądzę, że powinien on być ustawiony na QTableWidgetItem. Chciałbym zaktualizować model wewnętrzny w QAbstractTableModel, ale nie jestem pewien, jak to zrobić - lub znaleźć wiersz lub kolumna. Dzięki. – drexiya

+0

Uprościliśmy przykładowy kod, aby usunąć tę właściwość dataFrameToQtTable, mam nadzieję, że problem jest bardziej przejrzysty. – drexiya

Powiązane problemy