在 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)
这里有两个问题(我知道)。
if name != self.table.item(row, 0).text()
太直白了所以我不得不把它改成:
if name.lower() != self.table.item(row, 0).text().lower()
(重要)。是它没有检测到退格,但当我退格到显示多行的特定时刻时,我看不到它们,因为函数已经隐藏了它们。因此,例如我在 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 就足够了,并且会使您的问题变得更好。
我试过自己在我的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)
这里有两个问题(我知道)。
if name != self.table.item(row, 0).text()
太直白了所以我不得不把它改成:if name.lower() != self.table.item(row, 0).text().lower()
(重要)。是它没有检测到退格,但当我退格到显示多行的特定时刻时,我看不到它们,因为函数已经隐藏了它们。因此,例如我在 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 就足够了,并且会使您的问题变得更好。