2014-04-01 9 views
6

Ich bin neu in Qt Programmierung. Ich versuche, eine einfache Tabelle zu erstellen, in der Zeilen durch Klicken auf eine Schaltfläche hinzugefügt werden können. Ich kann die Tabelle gut implementieren, aber ich kann nicht scheinen, dass die aktualisierten Daten auf dem Tisch angezeigt werden. Ich glaube, dass mein Problem von der Tatsache herrührt, dass ich scheinbar keine Art von "Änderungsdaten" -Methode mit dem Knopf aufrufen kann. Ich habe mehrere verschiedene Online-Lösungen ausprobiert, von denen alle zu 4 Jahre alten, dead-end Posts geführt haben. Was ich bisher habe, ist die Grundstruktur, ich kann einfach nicht herausfinden, wie man die Tabelle mit neuen Daten aktualisiert.PyQt: Hinzufügen von Zeilen zu QTableView mit QAbstractTableModel

Dies ist die grundlegende Ansicht

ich mit einigen Testdaten eingerichtet haben.

In der endgültigen Implementierung wird die Tabelle leer gestartet und ich möchte Zeilen anhängen und in der Tabellenansicht anzeigen lassen.

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

Vielen Dank für den Beispielcode! Sehr hilfreich! – Hephaestus

+0

Zustimmen .. Das Codebeispiel in Ihrer Frage ist eine Antwort auf viele andere Fragen. –

Antwort

3

Wenn die zugrunde liegenden Daten des Modells ändert, sollte das Modell emittieren entweder layoutChanged oder layoutAboutToBeChanged, so dass die Ansicht aktualisiert richtig (es gibt auch dataChanged, wenn Sie einen bestimmten Bereich von Zellen, die aktualisiert werden soll).

So brauchen Sie nur so etwas wie dieses:

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

Wäre nicht setData() auch im Modell erforderlich? Ich habe die gesamte Dokumentation durchgesehen und sehe Referenzen, die entweder setData() oder insertRows(), etc. haben müssen. Problem ist, ich bin nicht 100% sicher, wie man die setData() Methode implementiert oder was noch wichtiger ist nennen. - EDIT: Nun, ich habe gerade versucht, Ihre Bearbeitung und es funktionierte perfekt ohne die setData() -Methode, also denke ich, es ist nicht nötig! Ich schätze die Hilfe sehr! – user3439556

+0

Normalerweise müssen Sie setData() implementieren, wenn Sie ein bearbeitbares Raster haben möchten, um den korrekten Wert in Ihrem Modell zu aktualisieren. Beispiel: 'def setData (self, Index, Wert, Rolle = Qt.EditRole): wenn role == Qt.EditRole: setattr (self.arraydata [index.row()], self.columns [index. column()], value) self.dataChanged.emit (index, index,()) return Wahr else: return False' – TheGerm