[gelöst] Sort in QTableWidget

Alles rund um die Programmierung mit Qt
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

[gelöst] Sort in QTableWidget

Beitrag 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
Zuletzt geändert von dazedly am 4. Oktober 2010 22:37, insgesamt 3-mal geändert.
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag 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.
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

Beitrag 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.
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Ach, wir verwenden ein QTableWidget? Dann entweder ein angepasstes Delegate verwenden, oder den operator < vom QWidgetItem überladen.
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

Beitrag 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?
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Das QItemDelegate hatte ich zuvor schon mal erwähnt...
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

Beitrag 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 :(
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

Beitrag 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?
padreigh
Beiträge: 340
Registriert: 13. Mai 2010 10:06

Beitrag 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 ...
Patrick (QtCreator 1.3.1, Qt 4.6.3)
---
template = subdirs
padreigh
Beiträge: 340
Registriert: 13. Mai 2010 10:06

Beitrag 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 :)
Patrick (QtCreator 1.3.1, Qt 4.6.3)
---
template = subdirs
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

Beitrag 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?
padreigh
Beiträge: 340
Registriert: 13. Mai 2010 10:06

Beitrag 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);
}
Zuletzt geändert von padreigh am 5. Oktober 2010 08:29, insgesamt 1-mal geändert.
Patrick (QtCreator 1.3.1, Qt 4.6.3)
---
template = subdirs
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

Beitrag von dazedly »

padreigh vielen Dank!! Ich finde es furchtbar nett, dass du dir Zeit für mich genommen hast. Ich verstehe es endlich!

Danke!
padreigh
Beiträge: 340
Registriert: 13. Mai 2010 10:06

Beitrag 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, :D für [gelöst]
Patrick (QtCreator 1.3.1, Qt 4.6.3)
---
template = subdirs
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

Beitrag 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 :(
Antworten