2010-04-23 4 views
6

Tôi muốn tạo một trường tìm kiếm lọc các mục được hiển thị trong một QListView. Về cơ bản, người dùng có thể nhập "foo" và chỉ các mục có "foo" trong DisplayRole mới được hiển thị.Tạo một trường tìm kiếm QLineEdit cho các mục được hiển thị trong một QListView

Tôi đã có một vài ý tưởng về làm thế nào để làm điều này, nhưng nghĩ rằng tôi muốn hỏi những người có kinh nghiệm hơn I.

Ý tưởng của tôi sẽ được sử dụng một số tín hiệu và khe cắm để thiết lập một bộ lọc trong mô hình QAbstractItem và kích hoạt bản cập nhật() trong QListView.

Có phương pháp trợ giúp nào trong QListView để lọc tôi có thể đã bỏ lỡ không?

Có cách xử lý kinh điển nào mà tôi chưa chạy qua không?

chỉnh sửa

tiến bộ hiện tại.

Tôi đã tạo một khe công cộng có tên là "updateFilter (QString)" trong lớp con QFileSystemModel của tôi. Sau đó, tôi

connect(myQLineEditSearch, SIGNAL(textChanged(QString)), 
     myQFileSysModel, SLOT(updateFilter(QString))); 

này thiết lập các bộ lọc, sau đó trong QFileSystemModel tôi :: phương pháp dữ liệu (...), tôi có:

void ComponentModel::updateFilter(QString filter) 
    { 
    _filter = filter; 
    emit layoutChanged(); 
    } 

    QVariant ComponentModel::data(const QModelIndex &index, int role) const 
    { 
    QVariant result; 

    // if our search filter term is set and the item does not match, 
    // do not display item data. Searches are case insensitive 
    if (!_filter.isEmpty() && 
     !QFileSystemModel::data(index, Qt::DisplayRole) 
     .toString().toLower().contains(_filter.toLower())) 
    { 
     return result; 
    } 

    result = QFileSystemModel::data(index, role); 
    return result; 
    } 

này là gần như ở đó. Các "trục trặc" tôi đang làm việc trên đã làm với nơi đối tượng được hiển thị. Hiện tại, nếu tôi áp dụng tìm kiếm khớp với mục thứ 3 trong danh sách thì chỉ hai hàng đầu tiên được hiển thị dưới dạng trống. Nói cách khác, nó vẫn hiển thị các hàng cho các mục không khớp.

Trả lời

5

Trả lời câu hỏi của riêng mình cho tài liệu tham khảo.

Có vẻ như những gì cần thiết ở đây là QSortFilterProxyModel.

Mã này trông giống như sau:

QListView *myview = new QListView(this); 
MyModel *model = new MyModel(this); 
QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this); 

proxy->setSourceModel(model); 
myview->setModel(proxy); 

myview->setRootIndex(proxy->mapFromSource(model->index(model->rootPath())); 

connect(filterLineEdit, SIGNAL(textChanged(QString)), 
     proxy,   SLOT(setFilterFixedString(QString))); 

Vấn đề duy nhất tôi nhìn thấy ở đây là rootIndex dường như được thiết lập lại khi bạn nhập một chuỗi tìm kiếm. Tôi sẽ cập nhật khi tôi tìm ra điều đó.

3

Điều này sẽ làm việc cho một QListWidget ...

phương pháp này giúp tiết kiệm tất cả các mục được tìm thấy trong một QList từ đó bạn sau này có thể đọc chúng (ví dụ để hiển thị chúng trong cùng một hoặc một QListView mới):

void search_for_string(QString search_str) 
{ 
    QList<QListWidgetItem*> my_found_items; 

    for(int i = 0; i < my_list->count(); i++) 
    { 
     QListWidgetItem* current = my_list->item(i); 
     if(current->text().contains(search_str)) 
     { 
      my_found_items.append(current); 
     } 
    } 
} 

Và khi nhấn vào "Tìm kiếm" hay bất cứ điều gì, bạn gọi nó như thế:

search_for_string(my_line_edit->text()); 
+1

này có vẻ tốt, nhưng cũng có vẻ phụ thuộc vào người sử dụng bằng tay nhấp chuột vào một nút tìm kiếm hoặc một số như vậy.Tôi đang cố gắng cập nhật trực tiếp vào qlistview. Tôi đã cập nhật bài đăng của mình để phản ánh tiến độ hiện tại của tôi. – jkyle

2

Một giải pháp mà làm việc cho một QListWidget:

void SpeciePropertiesListWidget::filter(QString filter_string) 
{ 
    hide_all(); 
    QList<QListWidgetItem*> matches (m_list->findItems(filter_string, Qt::MatchFlag::MatchContains)); 
    for(QListWidgetItem* item : matches) 
    item->setHidden(false); 
} 

void SpeciePropertiesListWidget::hide_all() 
{ 
    for(int row(0); row < m_list->count(); row++) 
    m_list->item(row)->setHidden(true); 
} 

Và sau đó, kết nối QLineEdit:

QLineEdit * m_filter_le = new QLineEdit(this); 
SpeciePropertiesListWidget * list_widget = new SpeciePropertiesListWidget(this) 
connect(m_filter_le, SIGNAL(textEdited(QString)), list_widget, SLOT(refresh_filter(QString)));