2014-04-01 27 views
6

Jestem super nowy w programowaniu Qt. Próbuję utworzyć prostą tabelę, do której można dodawać wiersze, klikając przycisk. Mogę zaimplementować tabelę dobrze, ale nie mogę uzyskać zaktualizowanych danych do wyświetlenia na stole. Wierzę, że mój problem wynika z faktu, że nie mogę poprawnie nazwać metody "zmiany danych" za pomocą przycisku. Wypróbowałem kilka różnych rozwiązań online, z których wszystkie prowadziły do ​​4-letnich, ślepych etatów. To, co mam do tej pory, to podstawowa struktura, nie mogę po prostu dowiedzieć się, jak zaktualizować tabelę za pomocą nowych danych.PyQt: Dodawanie wierszy do QTableView przy użyciu QAbstractTableModel

Jest to podstawowy widok

Mam skonfigurować z niektórych danych testowych.

W ostatecznym wykonaniu tabela zacznie być pusta i chciałbym dodać wiersze i wyświetlić je w widoku tabeli.

import sys 
from PyQt4.QtCore import * 
from PyQt4.QtGui import * 

class MyWindow(QWidget): 
    def __init__(self): 
     QWidget.__init__(self) 

     # create table 
     self.get_table_data() 
     self.table = self.createTable() 

     # layout 
     self.layout = QVBoxLayout() 

     self.testButton = QPushButton("test") 
     self.connect(self.testButton, SIGNAL("released()"), self.test)   

     self.layout.addWidget(self.testButton) 
     self.layout.addWidget(self.table) 
     self.setLayout(self.layout) 

    def get_table_data(self): 
     self.tabledata = [[1234567890,2,3,4,5], 
          [6,7,8,9,10], 
          [11,12,13,14,15], 
          [16,17,18,19,20]] 

    def createTable(self): 
     # create the view 
     tv = QTableView() 

     # set the table model 
     header = ['col_0', 'col_1', 'col_2', 'col_3', 'col_4'] 
     tablemodel = MyTableModel(self.tabledata, header, self) 
     tv.setModel(tablemodel) 

     # set the minimum size 
     tv.setMinimumSize(400, 300) 

     # hide grid 
     tv.setShowGrid(False) 

     # hide vertical header 
     vh = tv.verticalHeader() 
     vh.setVisible(False) 

     # set horizontal header properties 
     hh = tv.horizontalHeader() 
     hh.setStretchLastSection(True) 

     # set column width to fit contents 
     tv.resizeColumnsToContents() 

     # set row height 
     tv.resizeRowsToContents() 

     # enable sorting 
     tv.setSortingEnabled(False) 

     return tv 

    def test(self): 
     self.tabledata.append([1,1,1,1,1]) 
     self.emit(SIGNAL('dataChanged()')) 
     print 'success' 

class MyTableModel(QAbstractTableModel): 
    def __init__(self, datain, headerdata, parent=None): 
     """ 
     Args: 
      datain: a list of lists\n 
      headerdata: a list of strings 
     """ 
     QAbstractTableModel.__init__(self, parent) 
     self.arraydata = datain 
     self.headerdata = headerdata 

    def rowCount(self, parent): 
     return len(self.arraydata) 

    def columnCount(self, parent): 
     if len(self.arraydata) > 0: 
      return len(self.arraydata[0]) 
     return 0 

    def data(self, index, role): 
     if not index.isValid(): 
      return QVariant() 
     elif role != Qt.DisplayRole: 
      return QVariant() 
     return QVariant(self.arraydata[index.row()][index.column()]) 

    def setData(self, index, value, role): 
     pass   # not sure what to put here 

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

    def sort(self, Ncol, order): 
     """ 
     Sort table by given column number. 
     """ 
     self.emit(SIGNAL("layoutAboutToBeChanged()")) 
     self.arraydata = sorted(self.arraydata, key=operator.itemgetter(Ncol))  
     if order == Qt.DescendingOrder: 
      self.arraydata.reverse() 
     self.emit(SIGNAL("layoutChanged()")) 

if __name__ == "__main__": 
    app = QApplication(sys.argv) 
    w = MyWindow() 
    w.show() 
    sys.exit(app.exec_()) 
+1

Dziękuję za przykładowy kod! Niezwykle pomocny! – Hephaestus

+0

Zgadzam się. Przykład kodu w pytaniu jest odpowiedzią na wiele innych pytań. –

Odpowiedz

3

Kiedy bazowe dane modelowych zmian, model powinien emitować zarówno layoutChanged lub layoutAboutToBeChanged, tak że pogląd aktualizacje prawidłowo (jest również dataChanged, jeśli chcesz zaktualizować określony zakres komórek).

więc wystarczy coś takiego:

def test(self): 
     self.tabledata.append([1,1,1,1,1]) 
     self.table.model().layoutChanged.emit() 
     print 'success' 
+0

Czy w modelu nie byłaby wymagana funkcja setData()? Przejrzałem całą dokumentację i ciągle widzę odniesienia do konieczności posiadania albo setData() albo insertRows(), itp. Problemem jest to, że nie jestem w 100% pewny jak zaimplementować metodę setData() lub, co ważniejsze, jak nazwać. - - EDIT: Cóż, po prostu wypróbowałem twoją edycję i działało idealnie bez metody setData(), więc domyślam się, że nie jest to konieczne! Naprawdę doceniam pomoc! – user3439556

+0

Zazwyczaj konieczne jest zaimplementowanie metody setData() w celu uzyskania edytowalnej siatki w celu zaktualizowania poprawnej wartości w modelu. Na przykład: 'def setData (self, index, value, role = Qt.EditRole): jeśli rola == Qt.EditRole: setattr (self.arraydata [index.row()], self.columns [indeks. kolumna()], wartość) self.dataChanged.emit (indeks, indeks,()) return True else: return False' – TheGerm