在 QTableWidget 中搜索

Searching In QTableWidget

我试过自己在我的QTableWidget上添加搜索功能,因为google上的教程要么与c++相关,要么与pyqt4相关。现在我知道如果我将它更改为 QTableView 有一个更简单的方法,所以如果没有其他选择,我将更改它。

这是我目前的解决方案。

class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.table = QTableWidget(self)
        self.search = QLineEdit(self)
        self.table.setColumnCount(2)

        self.table.setHorizontalHeaderItem(0, QtWidgets.QTableWidgetItem('Name'))
        self.table.setHorizontalHeaderItem(1, QtWidgets.QTableWidgetItem('Age'))

        people = {'Bob': '43', 'Jeff': '22', 'Juan': '30'}
        self.table.setRowCount(len(people))
        for num, name in enumerate(people):
            name = QTableWidgetItem(name)
            age = QTableWidgetItem(people[name])
            
            self.table.setItem(num, 0, name)
            self.table.setItem(num, 1, age)
        
        self.search.textChanged.connect(self.findName)
    
    def findName(self):
        name_to_find = self.search.text()
        table_rows = self.table.rowCount()
        if table_rows != 0 and len(name) != 0:
            for row in range(self.table.rowCount()):
                if name_to_find not in self.table.item(row, 0).text():
                    self.table.hideRow(row)
        else:
            for row in range(table_rows):
                self.table.showRow(row)

这里有两个问题(我知道)。

  1. if name != self.table.item(row, 0).text() 太直白了所以我不得不把它改成: if name.lower() != self.table.item(row, 0).text().lower()

  2. (重要)。是它没有检测到退格,但当我退格到显示多行的特定时刻时,我看不到它们,因为函数已经隐藏了它们。因此,例如我在 lineedit 中写 'jeff' 并退格直到 j。它没有显示胡安。我必须先清除 lineedit 才能显示所有内容。我想到的一个解决方案是添加一个 showRow 函数。 (我在写的时候就想到了这个,我会在完成后立即尝试)

无论如何,这个 post 的主要目的是找到一种更好的搜索 QTableWidget 的方法,所以我需要的是这个问题的答案,而不是我的解决方案。但是,如果你们有适合我的解决方案,也可以发表评论,这样我就可以松一口气了。

我的另一个想法是突出显示该行(更改背景颜色),但在 100 人的情况下很难找到突出显示。一个解决方案是滚动到项目 (.scrollToItem()),但如果用户不知道全名并且只知道 'J' 部分。由于有多个 J,它将滚动到哪里。

虽然隐藏和显示行对于小型数据模型可能没问题,但它需要一些小心和注意,否则它通常会像您一样产生一些逻辑问题。为了将来参考,请考虑使用 QSortFilterProxyModel.

问题是,只要“搜索查询”与项目匹配,您就只是隐藏行,但如果其他行是,则您不会恢复它们,因为您只在查询为空时才这样做。

解决方案非常简单:使用 setRowHidden 代替 showRow()/hideRow(),使用基于 negative[ 的 hide 参数=27=] 匹配:

    def findName(self):
        name = self.search.text().lower()
        for row in range(self.table.rowCount()):
            item = self.table.item(row, 0)
            # if the search is *not* in the item's text *do not hide* the row
            self.table.setRowHidden(row, name not in item.text().lower())

一个不相关的注释:总是喜欢布局管理器;虽然你的只是一个简单的例子,但 UI 元素像这样重叠并不是一件好事(这有点令人迷惑和烦人,即使对于一个基本的代码示例也是如此:例如, window 显示非常小,当调整大小时 table 保持其小尺寸,并且 headers 不可见,因为它们被 QLineEdit 隐藏了)。创建好的问题还包括使用提供的代码创建好的结果:一个简单的 QVBoxLayout 就足够了,并且会使您的问题变得更好。