Nominate our 2022 Qt Champions!

sort the items on QTreeWidget/QListWidget, use QTreeWidgetItem::data().toInt()

  • sort the items on QTreeWidget/QListWidget.
    i use quickSort algorithm.
    i want to know can i use QTreeWidgetItem::data().toInt() as the value to be sorted?
    will this method work fine for both string, int, text, etc?

  • Moderators

    No, it will not work for strings or any non-numerical value. See the docs.
    data returns QVariant. QVariant has comparison operators so you can sort it without converting it to anything. This will work for most standard and Qt types.
    If you want to sort a custom type stored in QVariant make sure it has comparison operators (at least == and <) defined and registered.

  • no, i want to use QTreeWidgetItem::data().toInt() to convert various kinds of data(including string) into Int, and then use quickSort algorithm to sort these Int , in order to sort there related WidgetItem.
    is this right?

  • and if i can't use this method to sort by string, is there existed method to sort by string(eg. name in the 1st column) ?

  • Moderators

    In that case just use sortItems.

    No, converting strings (or any other data) to int (or anything else) is never a good way to sort them. Giving them a proper comparison operators (like I mentioned) and sorting them directly is the right way.

  • @opengpu2 You can subclass QTreeWidgetItem and create your own item. Then re-implement operator< and return true or false depending upon your conditions.

    is there any demos?
    should i re-implement operator< , operator>....and anything else?

  • Returns the variant as an int if the variant has userType() QMetaType::Int, QMetaType::Bool, QMetaType::QByteArray, QMetaType::QChar, QMetaType::Double, QMetaType::LongLong, QMetaType::QString, QMetaType::UInt, or QMetaType::ULongLong; otherwise returns 0.

    from the docs,
    it seems that QString will work fine.

  • Moderators

    No, it will work only for strings representing a number i.e.

    qDebug() << QVariant(QString("hello")).toInt(); // prints 0
    qDebug() << QVariant(QString("world")).toInt(); // prints 0
    qDebug() << QVariant(QString("42")).toInt();    // prints 42

    I can only repeat the third time. There's absolutely no need whatsoever to convert QVariant or QString to int just to sort it. QVariant has operator< so is sortable directly. For standard types (ints, doubles, strings etc.) contained in QVariant you don't need to do anything extra. Just call sortItems. It will sort by the column you choose using string comparison of the text displayed in wanted column.

    Only operator< is required to make type sortable as most sorting algorithms only use that. If they need anything else they will express other operators in terms of operator< i.e. a==b -> !(a<b || b<a), a>b -> b<a.

  • when i re-implement operator<, how can i sort depend on various "column" data , not only the DisplayRole data.
    why i do this is i want have a QTreeWidget and a QListWidget, which have the Same contents.

    1. i sort the QTreeWidget items by the data on a column.
    2. when i switch into the QListWidget, i will sort by the same data with the QTreeWidget, sort the i need more than sort by the DisplayRole

  • Moderators

    Gosh, sorry, but it's really hard to help you because you keep changing the requirements slightly and post multiple questions asking the same thing in a different context, which changes the suggested approaches. Right now you are mixing a lot of independent concepts like sorting, data roles and QVariant conversions.

    For the latest scenario (a tree and list widgets) the Q*Widget classes are not the right tool.
    It sounds like you've got a single piece of data displayed differently in two views. For this create one model (either QStandardItemModel or a custom one derived from QAbstractItemModel). Then create two proxy models based on QSortProxyFilterModel and set them as models on a QTreeView and QListView. In each of the proxy models implement the lessThen method that compares two items. The items are represented as QModelIndex so you can access any role via data() member of the items.
    the data() method returns a QVariant. Depending on the role it holds different types. Don't convert them to int or anything else. QVariant can be compared directly. If you know what kind of data it holds (e.g. QString for Qt::DisplayRole) then you can use toString() method of the variant and then customize your lessThen method using this value.

  • sorry..right now, my question is:
    how can i sort the items in QListWidget not only by the Qt::DisaplayRole, but also the other data which i setData() by myself, and make it possible to dynamically change the basis of what i am sorting by.

  • i think i got it:
    i will wirte like this:
    int index = this->listWidget()->GetMyIndex();
    //depend on this index, i get the different data.
    //then sort the data just got....

Log in to reply