2011-10-21 42 views
10

Tôi có một QTableWidget và cột đầu tiên chứa các số từ 1 đến 1000. Bây giờ tôi cần sắp xếp bảng dựa trên cột đầu tiên này.Cách sắp xếp dữ liệu trong QTableWidget?

Tôi đang sử dụng 'sortItems (int cột, Qt :: AscendingOrder)' chức năng, nhưng nó được hiển thị như: 1, 10, 100, 1000, 101, 102, ...

Nhưng Tôi cần kết quả là: 1, 2, 3, 4 ...., 1000.

Tôi đang sử dụng tệp csv để điền bảng. Bất kỳ ai có thể giúp tôi trong việc này?

Trả lời

9

Cách dễ nhất có thể là phân lớp QTableWidgetItem và sau đó triển khai toán tử < để thông minh về thực tế là bạn sắp xếp số và không phải là chuỗi.

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

Sau đó, khi bạn điền bảng của mình, bạn có thể chuyển trường hợp các mục tùy chỉnh biết cách sắp xếp chính xác thay vì các mục chung.

+1

Câu trả lời hoàn hảo! Mã này làm việc xuất sắc cho tôi. – zeFree

+0

Cảm ơn, công trình này. Trong các phiên bản mới hơn của Qt, chữ ký đã thay đổi thành 'bool operator <(const QTableWidgetItem & other) const' – iliis

+0

Nghiêm túc, nếu' setData (Qt :: DisplayRole, num) 'không hoạt động cho bạn, bạn nên thử . – Wesley

17

Giá trị được sắp xếp dưới dạng chuỗi vì bạn đã lưu chúng như vậy trong mô hình.

Các QVariant thể nhớ các loại ban đầu của dữ liệu nếu bạn để cho nó làm việc chuyển đổi bản thân, và các toán tử so sánh từ kiểu đó sẽ được sử dụng khi sắp xếp:

// 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);  

Biên tập viên di động cũng sẽ thích ứng với loại của QVariant:

  • QSpinBox cho int,
  • QDoubleSpinBox cho doublefloat,
  • QDateTimeEdit cho QDateTime
  • ...
+0

Tôi đã sử dụng 'item.setData (Qt :: EditRole, valueFromCsvFile)' và bây giờ nó hoạt động tốt. Cảm ơn !! – Shyam

+0

@Shyam, tại sao không đặt câu trả lời này là câu trả lời được chấp nhận? Tôi đã gặp rắc rối với điều này bởi vì tôi đã sử dụng một int dài, và weirdly QVariant sẽ làm việc với int dài hoặc int dài, nhưng không dài int. Đúc lâu dài của tôi để qlonglong làm việc cho tôi. –

2

Một cách mà làm việc trong hoàn cảnh của tôi đã

1) trước khi điền bảng, tắt sắp xếp:

table.setSortingEnabled(False) 

2) pad các chuỗi số với khoảng trắng và làm cho tất cả các chuỗi trong cột có cùng độ dài:

(' '+numStr)[-4:] 

3) sau khi điền bảng, rẽ vào sắp xếp:

table.setSortingEnabled(True) 

này cố định hàng sắp xếp vấn đề và số thứ tự.

2

Tôi không biết câu trả lời được chấp nhận có được sử dụng để hoạt động hay không, nhưng với Qt5.1 thì không. Để hoạt động, định nghĩa operator< phải khớp với định nghĩa ảo từ qtablewidget.h.

Một bổ sung thú vị khác là sắp xếp các mục có số, nhưng bắt đầu bằng ký hiệu tiền tệ ($ hoặc chẳng hạn) hoặc kết thúc bằng %.

Đây là mã Cập nhật:

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(); 
    } 
}; 

Sau đó, bạn thêm các mục có chứa số sử dụng một cái gì đó như thế này:

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

Lưu ý rằng lớp này phải được sử dụng với số lượng chỉ , nó sẽ không sắp xếp đúng chuỗi (cũng như trường hợp với câu trả lời được chấp nhận).

Các vấn đề liên quan