2016-05-13 10 views
2

Dies ist mein erster Beitrag hier, aber ich habe eine Menge Hilfe von euch allen bekommen, seit ich angefangen habe zu programmieren.Wie können die zugrunde liegenden Daten von QAbstractTableModel vollständig geändert werden?

Ich bin neu in Qt und versuche im Moment mein erstes Projekt zu machen. Meine Frage betrifft die Kommunikation zwischen dem Modell, den zugrunde liegenden Daten und der Sichtweise.

Ich habe zuerst die Hintergrund-Dinge (Datenspeicherung etc.) von der GUI getrennt. Jetzt habe ich eine Vorlage Klasse Matrix und ich schrieb eine Vorlage Klasse MatrixModel, die von QAbstractTableModel erbt. Dies funktioniert gut, bedeutet, dass ich die Tabelle bearbeiten kann und die Werte in der Ansicht und in den Daten vom Modell aktualisiert werden.

Nun meine Frage: Wie ändere ich die Daten im Modell, ohne eine neue Methode zu schreiben?

mainwindow.cpp:

matrix<int> m = {{1,2,3},{4,5,6},{7,8,9}}; 
MatrixModel<int>* model = new MatrixModel<int>(m); 
QTableView* tableView = new QTableView; 
tableView->setModel(model); 

Gibt es eine Möglichkeit m.transpose() auf das Modell der zugrunde liegenden Daten zu nennen? Was passiert, wenn ich m ändere? Beeinflusst es die Daten des Modells? Ich habe viele Dinge ausprobiert, aber nichts hat funktioniert. Ein "Problem" ist, dass ich Standard-Signal/Slot-Syntax nicht verwenden kann, weil ich mit Template-Klassen arbeite.

Mein letzter Versuch war eine Update Klasse im Modell zu machen:

template<typename T> 
void MatrixModel<T>::updateAll() { 
    QModelIndex topLeft = index(0,0); 
    QModelIndex bottomRight = index(rowCount()-1, columnCount()-1); 
    emit dataChanged(topLeft, bottomRight); 
} 

und ich versuchte es mit einem Knopf zu verbinden und eine Lambda-Funktion:

connect(transposeButton, &QPushButton::clicked, [=,&m,&model]() { 
m.transpose(); model->updateAll(); 
}); 

aber das schien zu abstürzen mein Programm, wenn ich den Knopf drücke. Ich bin wirklich verzweifelt xD hoffe du kannst mir helfen. Wenn Sie weitere Informationen benötigen, wenden Sie sich bitte einfach ^^

Mit freundlichen Grüßen

Dennis

EDIT 1: Okay, so weit ich herausgefunden (mit Ihrer Hilfe :)), dass ich die Funktionen schreiben haben, die Matrix erneut im Modell (z. B. transpose()) und Datenänderungen von dort (mit emittieren dataChanged oder beginResetModel() ...), aber ich kann die zugrunde liegenden Daten Modelle nicht ändern. Wenn ich

schreibe dies im Hauptfenster: Abstürze

template<typename T> 
void MatrixModel<T>::transpose() { 
    m(0,0) = 5; 
} 

mein Programm nur, wenn ich die Taste transponieren drücken:

connect(transposeButton, &QPushButton::clicked, [&model]() { 
    model->transpose(); 
}); 

dies im Modell. Wenn ich die Zeile

m(0,0) = 5; 

kommentieren, funktioniert alles.

EDIT 2: Vielleicht gibt es ein Problem mit der Datenspeicherung, so ist hier mein Copykonstruktor und die privaten Variablen meiner Matrix-Klasse:

private: 
std::vector <T> data; 
size_t rows, columns; 

//Copy constructor 
template<typename T> 
matrix<T>::matrix(const matrix<T>& other) 
    : rows(other.rows), columns(other.columns) { 
    data = other.data; 
} 
+0

Wenn sich die Abmessungen deines Modells ändern, 'dataChanged() 'Signal ist nicht genug. Sie sollten 'beginResetModel()' aufrufen, bevor Sie Daten ändern, und dann 'endResetModel()' aufrufen, wenn Sie fertig sind. . . – Mike

+0

Wenn also Ihre Matrix nicht quadratisch ist, kann der Aufruf von 'transpose()' nur das 'dataChanged()' Signal auslösen und zu ungültigen Indizes in Ihrer Matrix führen. – Mike

+0

Okay, ich verstehe, aber ich kann nur anrufen das von meinem Modell. Aber ich rufe die Funktion m.transpose() von meinem Hauptfenster.cpp auf, wo ich das beginResetModel nicht aufrufen kann (weil es geschützt ist). Und ich möchte nicht alle Funktionen in meinem Matrixmodell neu schreiben. – syc

Antwort

0

Ich habe es ...

connect(transposeButton, &QPushButton::clicked, [model]() { 
    beginResetModel(); 
    m(0,0)=50; 
    endResetModel(); 
}); 

Werke ... Modell bereits ein Zeiger, also gebe ich den gleichen Zeiger auf die Lambda-Funktion. Jetzt muss ich nur herausfinden, was mit meiner Transpose-Funktion nicht stimmt, denn das funktioniert immer noch nicht, aber die Abstürze sind vorbei: P danke für deine Vorschläge :)

1

Sie sollten Ihre matrix Variable als privates Mitglied haben in Ihrem Modell, so dass alle Änderungen an der matrix durch Funktionen in Ihrem Modell vorgenommen werden sollten. das bedeutet, dass Ihr Modell eine öffentliche transpose Funktion hat, die transpose auf Ihrem matrix Daten dann dataChanged() Signal sendet. Und Sie sollten keinen direkten Zugriff auf Ihre matrix haben, da eine Änderung ohne das Wissen des Modells nicht geben wird, was Sie wollen. Auf diese Weise liegt es nicht in Ihrer Verantwortung, nach jeder Änderung der matrix Variable updateAll aufzurufen, da Ihr Modell die Änderung vorgenommen und sich entsprechend aktualisiert hat. . .

+0

Okay, dachte nur: P also muss ich die Funktionen für mein Modell neu schreiben. Aber ich habe gelesen, dass wir resetmodel nicht verwenden sollten, weil es alles wieder malt. Wäre es nicht besser, von oben links nach unten rechts zu emittieren? Außerdem ist mein Programm abgestürzt, wenn ich versuche, Modellfunktionen aufzurufen (sogar einfache wie die neue Transpose-Funktion, bei der ich RepresentModel endResetModel transponiere. Thx für deine Hilfe :) – syc

+0

Ich fand heraus, dass das Entfernen von beginResetModel() und endResetModel() funktioniert. Die Bearbeitung von m im Modell funktioniert also. – syc

+0

Wenn die Dimensionen Ihres Modells nicht geändert werden, reicht es aus, 'dataChanged()' auszugeben, aber wenn sich Ihre Dimensionen ändern, sollten Sie Funktionen wie 'beginRemoveRow' oder' beginResetModel', oder .. und dann 'endRemoveRow' oder' endRemoveRow aufrufen '... nach dem Ändern der Datenstruktur – Mike

Verwandte Themen