2011-10-21 21 views
10

我有一個QTableWidget,第一列包含從1到1000的數字。現在我需要根據這第一列對錶格進行排序。如何對QTableWidget中的數據進行排序?

我使用的函數 'sortItems(INT柱,QT :: AscendingOrder)',但它顯示爲: 1,10,100,1000,101,102,...

但我需要的結果如下: 1,2,3,4 ...,1000.

我正在使用csv文件填充表格。有沒有人能幫我做這件事?

回答

9

最簡單的方法可能是對QTableWidgetItem進行子類化,然後實現<運算符,以便對數字排序而非字符串進行排序。

class MyTableWidgetItem : public QTableWidgetItem { 
    public: 
     bool operator <(const QTableWidgetItem &other) const 
     { 
      return text().toInt() < other.text().toInt(); 
     } 
}; 

然後當你填充你的表,你可以通過它知道如何給自己,而不是正常的一般的人排序的自定義項目的實例。

+1

完美答案!這段代碼對我來說非常合適。 – zeFree

+0

謝謝,這個工程。在更新版本的Qt中,簽名已經略微改變爲布爾運算符(const QTableWidgetItem&other)const' – iliis

+0

嚴重的,如果'setData(Qt :: DisplayRole,num)'不適合你,你應該試試這個。 – Wesley

17

這些值按字符串排序,因爲您將它們存儲在模型中。

QVariant能記住原始類型的數據的,如果你讓它做轉換本身,以及該類型的比較操作將被用於在排序時:

// Get the value from the CSV file as a numeric type 
int valueFromCsvFile = ...; 

// don't do this 
QTableWidgetItem *item = new QTableWidgetItem(QString::number(valueFromCsvFile)); 

// but do this instead 
QTableWidgetItem *item = new QTableWidgetItem; 
item.setData(Qt::EditRole, valueFromCsvFile);  

單元格編輯器也將適應所述的QVariant的類型:

  • QSpinBoxint
  • QDoubleSpinBoxdoublefloat
  • QDateTimeEditQDateTime
  • ...在我的情況下工作
+0

我用'item.setData(Qt :: EditRole,valueFromCsvFile)',現在它的工作正常。 謝謝! – Shyam

+0

@Shyam,爲什麼不把它作爲接受的答案呢?我遇到了麻煩,因爲我使用了一個long int,奇怪的是,QVariant會使用long long int或int,但不會使用long int。把我的長整數投給qlonglong爲我工作。 –

2

一種方法是

1)填寫表格前,請關閉排序:

table.setSortingEnabled(False) 

2)用空白填充數字串,並使列中的所有字符串具有相同的長度:

(' '+numStr)[-4:] 

3)填充所述表後,打開分選:

table.setSortingEnabled(True) 

這個固定的行排序問題和數值順序。

2

我不知道如果接受的答案用於工作,但與Qt5.1,它不。 爲了工作,operator<定義必須與qtablewidget.h的虛擬定義相匹配。

另一個有趣的添加是對具有數字的項目進行排序,但是以貨幣符號開頭(例如$)或以%結尾。

下面是更新後的代碼:

class TableNumberItem : public QTableWidgetItem 
{ 
public: 
    TableNumberItem(const QString txt = QString("0")) 
     :QTableWidgetItem(txt) 
    { 
    } 
    bool operator <(const QTableWidgetItem &other) const 
    { 
     QString str1 = text(); 
     QString str2 = other.text(); 

     if (str1[0] == '$' || str1[0] == '€') { 
      str1.remove(0, 1); 
      str2.remove(0, 1); // we assume both items have the same format 
     } 

     if (str1[str1.length() - 1] == '%') { 
      str1.chop(1); 
      str2.chop(1); // this works for "N%" and for "N %" formatted strings 
     } 

     double f1 = str1.toDouble(); 
     double f2 = str2.toDouble(); 

    return str1.toDouble() < str2.toDouble(); 
    } 
}; 

然後,添加包含使用這樣的數字項:

myTableWidget->setItem(row, col, new TableNumberItem("$0")); 

注意,此類必須與數字只能使用,它不會正確地對字符串進行排序(與接受的答案一樣)。

相關問題