Back-Link: https://www.hasenzaehn.ch/StaticHtml/wiki.html
Die Visualisierung der Materialdaten folgt dem Model–View–Controller (MVC)-Prinzip, erweitert um Qt-typische Models und Delegates für spezialisierte Darstellung (zb 3D, schöne Farben/Designs).
Ziel
| Schicht | Klasse / Technologie | Verantwortung |
|---|---|---|
| Domäne | MaterialData |
Reine Materialdaten |
| Controller | MaterialDataController |
Orchestrierung, State, Ableitungen |
| Model (Qt) | QAbstractTableModel |
View-Adapter für Tabellen |
| View | QML | Darstellung und Interaktion |
| Delegate | QML (TableView delegate) | Zell-Darstellung |
Der MaterialDataController ist das zentrale Bindeglied zwischen Backend-Daten und GUI.
Verantwortlichkeiten
LoadSource)MaterialData-Statesclass MaterialDataController : public QObject {
Q_OBJECT
Q_PROPERTY(QString id READ id NOTIFY materialChanged)
Q_PROPERTY(QString name READ name NOTIFY materialChanged)
Q_PROPERTY(QString spaceGroup READ spaceGroup NOTIFY materialChanged)
Q_PROPERTY(double a READ a NOTIFY materialChanged)
Q_PROPERTY(double b READ b NOTIFY materialChanged)
Q_PROPERTY(double c READ c NOTIFY materialChanged)
Q_PROPERTY(double alpha READ alpha NOTIFY materialChanged)
Q_PROPERTY(double beta READ beta NOTIFY materialChanged)
Q_PROPERTY(double gamma READ gamma NOTIFY materialChanged)
Q_PROPERTY(double density READ density NOTIFY materialChanged)
Q_PROPERTY(QVariantList wyckoffSites READ wyckoffSites NOTIFY materialChanged)
Q_PROPERTY(QVector3D polarization READ polarization NOTIFY materialChanged)
Q_PROPERTY(int source READ source WRITE setSource NOTIFY sourceChanged)
};
QML sieht keine MaterialData-Struktur, alle Werte werden über Properties exponiert, änderungen werden über ein einziges Signal (materialChanged) propagiert
void MaterialDataController::loadMaterial(const QString &id)
{
m_loader->getMaterialDataAsync(
id.toStdString(),
[this](std::expected<MaterialData, FetchError> result) mutable
{
if (!result) {
// Fehler an ui porpagieren
emit errorChanged(...);
return;
}
m_material = result.value();
recomputePolarization();
emit materialChanged();
});
}
Der Controller blockiert nie, die Loader-Strategie ist austauschbar,Callback landet bereits im GUI-Thread und Der Controller ist zustandsführend, nicht die View
Qt-Views (TableView, ListView, etc.) arbeiten nicht direkt mit C++-Objekten, sondern mit Models.
Diese Models adaptieren den Controller-State für die View
class LatticeTableModel : public QAbstractTableModel {
Q_OBJECT
public:
explicit LatticeTableModel(MaterialDataController *controller);
private slots:
void onMaterialChanged();
};
QVariant LatticeTableModel::data(const QModelIndex &index, int role) const
{
if (role != Qt::DisplayRole) return {};
switch (index.row()) {
case 0: return index.column() == 0 ? "a" : QString::number(m_controller->a()) + " Å";
case 1: return index.column() == 0 ? "b" : QString::number(m_controller->b()) + " Å";
case 2: return index.column() == 0 ? "c" : QString::number(m_controller->c()) + " Å";
case 3: return index.column() == 0 ? "α" : QString::number(m_controller->alpha()) + " °";
case 4: return index.column() == 0 ? "β" : QString::number(m_controller->beta()) + " °";
case 5: return index.column() == 0 ? "γ" : QString::number(m_controller->gamma()) + " °";
}
return {};
}
View aktualisiert sich automatisch, es braucht kein direkter QML-Zugriff auf Controller-Interna und Tabellenlogik bleibt vollständig in C++
void LatticeTableModel::onMaterialChanged()
{
beginResetModel();
endResetModel();
}
Die Wyckoff-Sites werden analog in einem eigenen QAbstractTableModel abgebildet.
Damit lassen sich problemlos: Filter, Sortierung, Auswahl, Hervorhebung einzelner Sites realisieren, ohne den Controller zu verändern.
QML ist ausschliesslich View:
Keine Geschäftslogik, kein Parsing, keine Berechnungen.
TableView {
model: latticeModel
delegate: Rectangle {
required property int column
required property var display
Text {
text: column === 0
? display
: (isNaN(Number(display)) ? display
: Number(display).toFixed(3))
horizontalAlignment:
column === 0 ? Text.AlignLeft : Text.AlignRight
}
}
}
Delegate-Prinzip: Delegate definiert Darstellung einer Zelle, Model liefert reine Daten,Formatierung (Einheiten, Rundung) passiert im View
