QAction und QTableView aktualisieren

Alles rund um die Programmierung mit Qt
Antworten
klaus85
Beiträge: 20
Registriert: 5. Oktober 2010 16:54

QAction und QTableView aktualisieren

Beitrag von klaus85 »

Hallo,

ich google mir schon nen wolf... Ich will per Kontextmenü einen Eintrag in einem QTableView ändern. Also es soll z.b. einfach der Text geändert werden. Ich hab die Action mit einer Methode connect-ed, in der ich den Eintrag per SQL mit "UPDATE..." ändere. Allerdings muss ich das Fenster neu öffnen, dass die Änderung im QTableView sichtbar wird. Ich hab schon versucht per connect(action, SIGNAL(triggered()), tableview, SLOT(repaint())); (oder dataChanged; hier kommt die Fehlermeldung: QObject::connect: Incompatible sender/receiver arguments
QAction::triggered() --> QTableView::dataChanged(QModelIndex,QModelIndex)) was zu erreichen, allerdings tut sich da auch nix...
Danke schon mal für den richtigen Hinweis.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Verwendest du denn kein QSqlTableModel? Wenn du Relationen abbilden willst, kannst du es mit ner QSqlRelationalTableModel versuchen. Ein eigener Delegate wäre auch zu überlegen.
Prinzipiell hört sich dein bisheriger Versuch recht hackig an. Aber ohne genauerer Beschreibung, was du genau machen willst und vor allem etwas Code (am besten das alte kompilierbare Minimalbeispiel) kann man wenig helfen.
klaus85
Beiträge: 20
Registriert: 5. Oktober 2010 16:54

Beitrag von klaus85 »

ich verwende für die QTableView ein QSqlQueryModel. Für mein Kontextmenü hab ich jetzt eine eigene Klasse geschrieben. Macht es da Sinn, das Model an das Kontexmenü mit zu übergeben? Wenn ich das mache und dann im Slot der Action nochmal das Model per setQuery() setze klappt es, aber ist das sauber, oder kann ich im Model einen Datensatz ändern (damit ich mir das setQuery spare...)?
padreigh
Beiträge: 340
Registriert: 13. Mai 2010 10:06

Beitrag von padreigh »

The QSqlQueryModel class provides a read-only data model for SQL result sets.
Guckst du hier:
http://doc.trolltech.com/4.7/sql-cachedtable.html
Patrick (QtCreator 1.3.1, Qt 4.6.3)
---
template = subdirs
klaus85
Beiträge: 20
Registriert: 5. Oktober 2010 16:54

Beitrag von klaus85 »

ok, also QSqlTableModel verwenden. Wie kann ich dann da den Datensatz über eine QAction ändern? Reicht es mir da, wenn ich das Model habe oder brauch ich noch die Tabelle (irgendwie muss der ja wissen, welche Datensätze - nämlich die selektierten - geändert werden müssen). Brauch ich da dann ein
QItemSelectionModel?

danke schon mal für die bisherige hilfe, echt toll!
padreigh
Beiträge: 340
Registriert: 13. Mai 2010 10:06

Beitrag von padreigh »

eigentlich solltest du da enfach in die Zelle des Views klicken können und das ändernd dann die Daten im Model. Es gibt ne Property im Model die bestimmt wann Änderungen zurück übertragen werden (setEditStrategy: OnFieldChange, OnRowChange, OnManualSubmit). Das view erlaubt Änderung in Zellen und nutzt dafür ein typabhängiges QDelegate (die du bei Bedarf generell, spalten oder zellenweise neu setzen kannst). Das view hat eine currentSelection über die man sicher auch was mit QActions machen kann ... oder über die mousePressEvent des Views ? ...
Patrick (QtCreator 1.3.1, Qt 4.6.3)
---
template = subdirs
klaus85
Beiträge: 20
Registriert: 5. Oktober 2010 16:54

Beitrag von klaus85 »

naja, über tabellenview direkt ändern will ich ja nicht haben, nur über das contextmenü mit der entsprechenden action... ich probier morgen mal.
klaus85
Beiträge: 20
Registriert: 5. Oktober 2010 16:54

Beitrag von klaus85 »

Hab's soweit hinbekommen. Jetzt hab ich aber das Problem, dass ich mehrere Fenster mit QTableViews habe, die teilweise auf die selben Daten zugreifen aber andere Models haben (die Tabellen haben nicht alle dieselben Spalten und z.T. auch gefilterte Inhalte; Stellt's euch vor wie ein Dispositionsprogramm für Fahrzeuge, denen der Disponent verschiedene Stati geben kann. Er kann dann einer Aufgabe z.b. die Fahrzeuge zuweisen->mehrere Aufgabenfenster, mit einer Übersicht über die daran gebundenen Fahrzeuge in einer QTableView; Dazu ein Dialog mit einer große Tabelle mit allen Fahrzeugen in der Übersicht).
Wenn ich jetzt in einer Tabelle was ändere (z.b. Fahrzeugstatus im Aufgabenfenster ändere), sollte das in der anderen aber synchron dargestellt werden (z.b. in der großen Übersicht). Was wäre da jetzt die beste Methode? Im Hauptfenster die Modelle definieren und dann an die Dialoge mitgeben (wobei man ein Unterfenster mit einer Tabelle auch mehrmals öffnen kann, das dann aber wieder andere Inhalte hat), als static deklarieren...?
klaus85
Beiträge: 20
Registriert: 5. Oktober 2010 16:54

Beitrag von klaus85 »

hat keiner eine Idee? Das selbe Model für "Übersicht alle Fahrzeuge" und "Übersicht Auftrag" verwenden geht leider nicht. Kann man die Models vielleicht irgendwie miteinander verbinden, dass das andere neu ladet wenn im einen was geändert wurde? Ich könnt zwar die Tabellen vermutlich über einen Timer jede Sekunde neu laden, aber das ist doch dann vermutlich Ressourcenverschwendung...

edit: bin gerade über proxy-models gestolpert. könnte das passen?
klaus85
Beiträge: 20
Registriert: 5. Oktober 2010 16:54

Beitrag von klaus85 »

ok, ich mache jetzt folgendes:
im MainWindow erstelle ich die Models und habe eine Methode, um die Models zu aktualisieren. In den Dialogen (Childs vom MainWindow) rufe ich dann die Methode auf, um die Models zu aktualisieren und so die Views aktualisieren zu können.
In meinem Contextmenü von einem Child-Dialog steht also

Code: Alles auswählen

MainWindow *main = dynamic_cast<MainWindow*>(m_ead->parentWidget()); //m_ead ist der Dialog
main->updateTables();
und in meiner MainWindow-Klasse

Code: Alles auswählen

void MainWindow::updateTables()
{
    qDebug() << "UPDATE TABLES";
    modelLaufendeAufgaben->select();
    modelUndisponierteAufgaben->select();
    fahrzeugemodel->select(); // Model für die große Übersicht
    qDebug() << "END UPDATE TABLES";
}
modelLaufendeAufgaben und modelUndisponierteAufgaben sind an je ein QTableView, die im MainWindow sind, drangehängt.
Das wird auch aufgerufen, allerdings ändern sich die Einträge nicht, erst wenn ich das Programm beende und neu öffne wird es korrekt dargestellt. Also hilft anscheinend das select() nichts. Wo steckt der Fehler?
klaus85
Beiträge: 20
Registriert: 5. Oktober 2010 16:54

Beitrag von klaus85 »

keiner eine Idee? Das kann doch nicht sein, dass ich da ein select drauf mache und es wird nix aktualisiert?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Der einzige schöne Weg ist ein ProxyModel. Ein und den selben Datensatz in verschiedene Models packen - eines für jede View - ist aufwändig und fehleranfällig.
Leider verschweigst du und, wie so eine Auswahl deiner Fahrzeuge zustande kommen soll. Kann man da einfach mit ner RegExp filtern? Oder gibts andere Kriterien. Je nachdem reicht dir schon das QSortFilterProxyModel, oder du musst ein eigenes ProxyModel (abgeleitet von QAbstractProxyModel) schreiben.
klaus85
Beiträge: 20
Registriert: 5. Oktober 2010 16:54

Beitrag von klaus85 »

Abgesehen vom Aufwand sollte das mit dem select doch trotzdem gehen?
-> edit: Fehler gefunden. Ich hab den Inhalt geändert mit

Code: Alles auswählen

mm->setData(m_ead->mm->index(index.row(), 7),1);
das geht anscheinend nur für die eine Tabelle, nicht für die anderen... Bin jetzt auf ein QSqlQuery umgestiegen, das geht jetzt mit dem select ohne Probleme...

Beim Auftrag erstellen gibt's einen Button zum Disponieren, beim Klick darauf sollen dann die freien Fahrzeuge angezeigt werden (sind mit einem Status in der Datenbank gekennzeichnet).
Allerdings gibt's noch eine andere Tabelle, in der definiert ist, welches Fahrzeug einem bestimmten Standort nach Priorität zugeteilt ist. Also Standort A werden Fahrzeuge 1, 2, 3 dieser Reihenfolge nach zuerst disponiert, Standort B 3, 1, 2 etc.[/code]
strige
Beiträge: 36
Registriert: 27. Dezember 2009 19:37

Beitrag von strige »

Hi, bin zwar erst neu in Qt, hatte aber bei mir ein ähnliches Problem.

Versuch mal nach deiner SQL anweisung:

QTableview->setModel(deinModel);

so habe ich meine Tabelle aktualisieren können ohne das Programm neuzustarten, habe mir deshalb eine methode geschrieben die meine neuen Daten aktualisiert und nach jeder Änderung kurz die Methode aufgerufen.
Hoffe ich konnte helfen.

lg strige
Antworten