Seite 1 von 2
[gelöst] Sort in QTableWidget
Verfasst: 3. Oktober 2010 18:52
von dazedly
Hallo Leute.
Ich habe das Problem, dass QTableWidget Items mit mit formatierten Europreisen + ¤ Zeichen als Inhalt nicht richtig sortiert wird. Jetzt meine Frage: Kann ich irgendwie einen zweiten Datensatz für das Item hinterlegen, damit es richtig sortiert wird? Ich konnte bisher nichts brachbares finden.
Gruß
Jens
Verfasst: 3. Oktober 2010 19:40
von upsala
Was heist nicht richtig sortiert? Könnte es sein, daß du eine Sortierung als Zahl willst, aber als Zeichenkette sortiert wird?
Hinterlege entweder deine Zahlen als int/float und verwende ein QItemDelegate, daß das ¤-Zeichen anhängt, oder hinterlege deine Zahlen mit data() in einer anderen Role.
Verfasst: 3. Oktober 2010 19:51
von dazedly
Das mit data und einer anderen Role habe ich schon versucht, aber welche Role soll das denn sein?
Code: Alles auswählen
QTableWidgetItem *priceTableWidgetItem = new QTableWidgetItem(QString::number(therapy->getPrice(), 'f', 2).append(QString::fromUtf8("¤")));
priceTableWidgetItem->setData(Qt::UserRole, therapy->getPrice());
Zeigt das richtige an, aber Sortiert falsch.
Code: Alles auswählen
QTableWidgetItem *priceTableWidgetItem = new QTableWidgetItem(QString::number(therapy->getPrice(), 'f', 2).append(QString::fromUtf8("¤")));
priceTableWidgetItem->setData(Qt::DisplayRole, therapy->getPrice());
Zeigt das falsche an, aber sortiert richtig.
Verfasst: 3. Oktober 2010 20:54
von upsala
Ach, wir verwenden ein QTableWidget? Dann entweder ein angepasstes Delegate verwenden, oder den operator < vom QWidgetItem überladen.
Verfasst: 3. Oktober 2010 21:20
von dazedly
upsala hat geschrieben:Ach, wir verwenden ein QTableWidget? Dann entweder ein angepasstes Delegate verwenden, oder den operator < vom QWidgetItem überladen.
Sorry, hatte mich beim erstellen von diesem Thread vertan.
Kannst du mir sagen, wo ich ein Beispiel für Delegate finde?
Verfasst: 3. Oktober 2010 21:36
von upsala
Das QItemDelegate hatte ich zuvor schon mal erwähnt...
Verfasst: 3. Oktober 2010 21:56
von dazedly
Ist mir klar, dass du das schon erwähnt hattest. Nur steige ich da noch nicht ganz durch. Ich blicke mit der Qt Doku in diesem Punkt nicht durch und alles was ich sonst noch finde sind entweder Python beispiele, oder zu spezifische.
Ich stehe noch in den Anfängen mit Qt und habe dafür auch schon recht viel damit gemacht, aber ich blicke hier jetzt nicht ganz durch

Verfasst: 3. Oktober 2010 23:32
von dazedly
Ich habe mir jetzt mal die ganze Sache in diesem Tutorial (
http://doc.trolltech.com/4.7/itemviews- ... egate.html) etwas genauer angesehen. Da wird Delegate benutzt um so ein Sternrating in einem QTableWidgetItem zu realisieren. Nur kann man selbst in diesem Tutorial nicht danach sortieren. Ich möchte doch nur einen ganz normalen String anzeigen. Da ist es doch überflüssig delegate zu benutzen... Ist Qt so beschränkend, dass ich nicht einfach nach alternativen Daten sortieren kann, ohne großen Aufwandt?
Verfasst: 4. Oktober 2010 17:37
von padreigh
was genau meinst du mit "sortiert falsch"?
(
http://doc.trolltech.com/4.6/qtablewidget.html#details)
f you want to enable sorting in your table widget, do so after you have populated it with items, otherwise sorting may interfere with the insertion order
Statt direkt ein TableWidget zu nehmen, könntest du dir ein QStandardItemModel zusammenbauen, das als Model eines QSortFilterProxyModels setzen und das in nem QTableView anzeigen lassen ...
Verfasst: 4. Oktober 2010 17:41
von padreigh
dazedly hat geschrieben:
Code: Alles auswählen
QTableWidgetItem *priceTableWidgetItem = new QTableWidgetItem(QString::number(therapy->getPrice(), 'f', 2).append(QString::fromUtf8("¤")));
priceTableWidgetItem->setData(Qt::UserRole, therapy->getPrice());
Sortiert falsch, weil dein QTableWidget immer nur nach der Qt::DisplayRole sortiert. Der Konstruktor setzt die Qt::UserRole korrekt und du schreibst was ins die UserRole die aber niemanden interessiert da es mE keinen Weg gibt dem QTableWidget zu sagen er soll diese Rolle als Sortier-Rolle nehmen .... höchstens durch Ableiten und selbst implementieren ...
Code: Alles auswählen
QTableWidgetItem *priceTableWidgetItem = new QTableWidgetItem(QString::number(therapy->getPrice(), 'f', 2).append(QString::fromUtf8("¤")));
priceTableWidgetItem->setData(Qt::DisplayRole, therapy->getPrice());
Sortiert richtig und zeigt falsch an weil du erst das richtige in die Qt::DisplayRole reinschreiben lässt (via Konstruktor) und dann manuell überschreibst (via setData) damit sortiert er nach der DisplayRole in der nun für deine Verhältnisse das Richtige drin steht

Verfasst: 4. Oktober 2010 17:57
von dazedly
Und wie ist die einfachste Lösung? Ist da echt nichts vorgesehen? QSortFilterProxyModels ist wie mit den Kanonen auf die Spatzen.
Ich wunder mich echt, warum es da nichts fertiges gibt... bin ich der erste, der sich das fragt?
Verfasst: 4. Oktober 2010 18:51
von padreigh
Was ist hieran Kanone und Spatzen? Das Proxy dazwischen zu stecken sind keine 10 Zeilen ... und du erhältst damit die Möglichkeit nach Spalten, nach verschiedenen Qt:Types und sonstiges zu sortieren ... und zu Filtern ...
Code: Alles auswählen
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui>
#include <QtCore>
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
public slots:
void sortUserRole() { proxy->setSortRole(Qt::UserRole); }
void sortDisplayRole() { proxy->setSortRole(Qt::DisplayRole); }
private:
QSortFilterProxyModel * proxy; //// 1 /////////////////////////////////////////
QStandardItemModel * model;
QTableView * view;
};
#endif // MAINWINDOW_H
Code: Alles auswählen
#include "mainwindow.h"
#include <algorithm>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent){
// amount of items
const int COUNT=3000;
// create view
view = new QTableView;
view->setSortingEnabled(true); //// 0 ( you need to set this anyway) /////////////////////////////////////////
// create model
model = new QStandardItemModel;
model->setRowCount(COUNT);
model->setColumnCount(1);
// create filter/sort proxy
proxy = new QSortFilterProxyModel; //// 2 /////////////////////////////////////////
// randomize prices
srand(time(0));
// some values
QVector<double> ms;
ms.reserve(COUNT);
// create prices
for (int i=0; i < COUNT; ++i)
{
ms.push_back( rand()%100000 / 1000.0 );
}
// randomize further by shuffling
std::random_shuffle(ms.begin(),ms.end());
// create items
for(int rowNr=0; rowNr<COUNT; rowNr++)
{
// one row
QStandardItem *sub = new QStandardItem;
// display role value (qstring !!)
sub->setData(QVariant(QString::number(ms.back(),' ',2)+QString::fromUtf8(" ¤")), Qt::DisplayRole);
// user role value (double !!)
sub->setData(QVariant(ms.back()),Qt::UserRole);
// insert it
model->setItem(rowNr,0,sub);
// remove value from vector
ms.pop_back();
}
// use standard model als model for proxy
proxy->setSourceModel(model); //// 3 /////////////////////////////////////////
proxy->setSortRole(Qt::DisplayRole); //// still 3 (thats the default, just uttering it for your convenience) /////////////////////////////////////////
// use proxy as model for view
view->setModel(proxy); //// still 3 (you need to set one datasource anyway)
// sort buttons
QPushButton * pb1 = new QPushButton("Sort after Qt::DisplayRole");
connect(pb1,SIGNAL(clicked()),this,SLOT(sortDisplayRole()));
QPushButton * pb2 = new QPushButton("Sort after Qt::UserRole");
connect(pb2,SIGNAL(clicked()),this,SLOT(sortUserRole()));
QWidget * w = new QWidget;
QVBoxLayout * l = new QVBoxLayout(w);
l->addWidget(pb1);
l->addWidget(pb2);
l->addWidget(view);
setCentralWidget(w);
}
Verfasst: 4. Oktober 2010 22:37
von dazedly
padreigh vielen Dank!! Ich finde es furchtbar nett, dass du dir Zeit für mich genommen hast. Ich verstehe es endlich!
Danke!
Verfasst: 5. Oktober 2010 08:34
von padreigh
dazedly hat geschrieben: Ich verstehe es endlich!
Ich habe nur gemacht was upsala vorschlug:
upsala hat geschrieben: Hinterlege [...] deine Zahlen mit data() in einer anderen Role.
Selber machen wäre edukativ gesehen vielleicht besser gewesen. Ich hab bloss deine Problembeschreibung auf ein kleines Beispiel runtergebrochen, sowas nennt sich Minimalbeispiel ... das selbst zu machen solltest du dir vielleicht angewöhnen. Wenn du sowas postest dann kann dir schneller geholfen werden ... und meist lernst du beim Erstellen des Minimalbeispiels mehr als du denkst - und manchmal/meist löst sich dein Problem von alleine weil du bemerkst wo es liegt, oder feststellst das die Stelle die du im Auge hattest damit überhaupt nix damit zu tun hat. Im Idealfall lokalisierst du den Fehler anderswo und wenn der dann nicht lösbar ist, kannst du zumindest bessere Fragen im Forum stellen ...... [Mund,fusslig,...]
//edit: -v,

für [gelöst]
Verfasst: 5. Oktober 2010 10:46
von dazedly
Ich hab dein Beispiel jetzt nachgearbeitet. Ich hab nicht einfach Copy+Paste gemacht, sondern mir alles genau angesehen. So habe ich wieder ein Stückweit etwas gelernt

Nur muss ich jetzt feststellen, dass mir nur für eine richtige Sortierung viel Kompfort verloren geht, da Die meisten Funktionen nicht mehr verfügbar sind, welche ich noch mit meinem QTableWidget hatte.
In meinen Augen ist diese Lösung immernoch nicht optimal, weil ein zweiter Datensatz offensichtlich so einfäch wäre
