有隐藏项时关注下一个 QListWidget 项
Focusing on the next QListWidget item while there are hidden items
在说我的问题之前,我想先说说我想做什么。
- 我希望我在
QLineEdit
中写的单词的结果出现在 QListWidget
中。
- 我想用键盘关注结果。
如果我用鼠标单击 Qlistwidget 并将焦点放在那里,即使有隐藏的项目,我也可以使用键盘(up/down 箭头键)关注下一个项目。系统自动完成,无需编写任何代码。
但我想在不失去对 QLineEdit
的关注的情况下做到这一点。所以我决定使用 QShortcut
:
self.__up_key = QShortcut(Qt.Key_Up, self)
self.__dw_key = QShortcut(Qt.Key_Down, self)
self.__up_key.activated.connect(self.__ctrl)
self.__dw_key.activated.connect(self.__ctrl)
def __ctrl(self):
curr = self._list_widget.currentRow()
if self.sender().key().toString() == "Up":
self._list_widget.setCurrentRow(curr - 1)
else:
self._list_widget.setCurrentRow(curr + 1)
在没有隐藏物品的情况下是这样的。但是如果有隐藏的项目,它们的索引仍然存在,所以即使下一个项目被隐藏,它也会选择它。这个当然看不到了。
而我得出这样的结论:
def __ctrl(self):
if self.sender().key().toString() == "Up":
self._list_widget.setCurrentRow(self.prevVisibleItem())
else:
self._list_widget.setCurrentRow(self.nextVisibleItem())
def nextVisibleItem(self):
for row in range(self._list_widget.currentRow() + 1, self._list_widget.count()):
if not self._list_widget.isRowHidden(row):
return row
return self._list_widget.currentRow()
def prevVisibleItem(self):
for row in range(self._list_widget.currentRow() - 1, -1, -1):
if not self._list_widget.isRowHidden(row):
return row
return self._list_widget.currentRow()
我检查每个项目是否隐藏。这对我有用,但我正在寻找一种更有效的方法。当我专注于 QListWidget 时,我可以在每个项目之间导航而无需编写任何代码。我想知道这是怎么发生的。
最小示例:
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QListWidget, QLineEdit, QShortcut
class Window(QWidget):
def __init__(self):
super().__init__()
self._layout = QVBoxLayout()
self.entry = QLineEdit()
self.entry.setPlaceholderText("Search")
self._list_widget = QListWidget()
__items = [str(i) + "- item" for i in range(6)]
self._list_widget.addItems(__items)
__hidden_items = [self._list_widget.item(1), self._list_widget.item(3), self._list_widget.item(5)]
for i in __hidden_items:
i.setHidden(True)
self.__up_key = QShortcut(Qt.Key_Up, self)
self.__dw_key = QShortcut(Qt.Key_Down, self)
self.__up_key.activated.connect(self.__ctrl)
self.__dw_key.activated.connect(self.__ctrl)
self._layout.addWidget(self.entry)
self._layout.addWidget(self._list_widget)
self.setLayout(self._layout)
self.show()
def __ctrl(self):
if self.sender().key().toString() == "Up":
self._list_widget.setCurrentRow(self.prevVisibleItem())
else:
self._list_widget.setCurrentRow(self.nextVisibleItem())
def nextVisibleItem(self):
for row in range(self._list_widget.currentRow() + 1, self._list_widget.count()):
if not self._list_widget.isRowHidden(row):
return row
return self._list_widget.currentRow()
def prevVisibleItem(self):
for row in range(self._list_widget.currentRow() - 1, -1, -1):
if not self._list_widget.isRowHidden(row):
return row
return self._list_widget.currentRow()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec_())
更优雅的解决方案是使用 moveCursor 获取 QModelIndex 并将当前索引设置为视图:
def __ctrl(self):
shorcut = self.sender()
index = QModelIndex()
if shorcut.key() == QKeySequence(Qt.Key_Up):
index = self._list_widget.moveCursor(
QAbstractItemView.MoveUp, Qt.NoModifier
)
elif shorcut.key() == QKeySequence(Qt.Key_Down):
index = self._list_widget.moveCursor(
QAbstractItemView.MoveDown, Qt.NoModifier
)
if index.isValid():
self._list_widget.setCurrentIndex(index)
在说我的问题之前,我想先说说我想做什么。
- 我希望我在
QLineEdit
中写的单词的结果出现在QListWidget
中。 - 我想用键盘关注结果。
如果我用鼠标单击 Qlistwidget 并将焦点放在那里,即使有隐藏的项目,我也可以使用键盘(up/down 箭头键)关注下一个项目。系统自动完成,无需编写任何代码。
但我想在不失去对 QLineEdit
的关注的情况下做到这一点。所以我决定使用 QShortcut
:
self.__up_key = QShortcut(Qt.Key_Up, self)
self.__dw_key = QShortcut(Qt.Key_Down, self)
self.__up_key.activated.connect(self.__ctrl)
self.__dw_key.activated.connect(self.__ctrl)
def __ctrl(self):
curr = self._list_widget.currentRow()
if self.sender().key().toString() == "Up":
self._list_widget.setCurrentRow(curr - 1)
else:
self._list_widget.setCurrentRow(curr + 1)
在没有隐藏物品的情况下是这样的。但是如果有隐藏的项目,它们的索引仍然存在,所以即使下一个项目被隐藏,它也会选择它。这个当然看不到了。
而我得出这样的结论:
def __ctrl(self):
if self.sender().key().toString() == "Up":
self._list_widget.setCurrentRow(self.prevVisibleItem())
else:
self._list_widget.setCurrentRow(self.nextVisibleItem())
def nextVisibleItem(self):
for row in range(self._list_widget.currentRow() + 1, self._list_widget.count()):
if not self._list_widget.isRowHidden(row):
return row
return self._list_widget.currentRow()
def prevVisibleItem(self):
for row in range(self._list_widget.currentRow() - 1, -1, -1):
if not self._list_widget.isRowHidden(row):
return row
return self._list_widget.currentRow()
我检查每个项目是否隐藏。这对我有用,但我正在寻找一种更有效的方法。当我专注于 QListWidget 时,我可以在每个项目之间导航而无需编写任何代码。我想知道这是怎么发生的。
最小示例:
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QListWidget, QLineEdit, QShortcut
class Window(QWidget):
def __init__(self):
super().__init__()
self._layout = QVBoxLayout()
self.entry = QLineEdit()
self.entry.setPlaceholderText("Search")
self._list_widget = QListWidget()
__items = [str(i) + "- item" for i in range(6)]
self._list_widget.addItems(__items)
__hidden_items = [self._list_widget.item(1), self._list_widget.item(3), self._list_widget.item(5)]
for i in __hidden_items:
i.setHidden(True)
self.__up_key = QShortcut(Qt.Key_Up, self)
self.__dw_key = QShortcut(Qt.Key_Down, self)
self.__up_key.activated.connect(self.__ctrl)
self.__dw_key.activated.connect(self.__ctrl)
self._layout.addWidget(self.entry)
self._layout.addWidget(self._list_widget)
self.setLayout(self._layout)
self.show()
def __ctrl(self):
if self.sender().key().toString() == "Up":
self._list_widget.setCurrentRow(self.prevVisibleItem())
else:
self._list_widget.setCurrentRow(self.nextVisibleItem())
def nextVisibleItem(self):
for row in range(self._list_widget.currentRow() + 1, self._list_widget.count()):
if not self._list_widget.isRowHidden(row):
return row
return self._list_widget.currentRow()
def prevVisibleItem(self):
for row in range(self._list_widget.currentRow() - 1, -1, -1):
if not self._list_widget.isRowHidden(row):
return row
return self._list_widget.currentRow()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec_())
更优雅的解决方案是使用 moveCursor 获取 QModelIndex 并将当前索引设置为视图:
def __ctrl(self):
shorcut = self.sender()
index = QModelIndex()
if shorcut.key() == QKeySequence(Qt.Key_Up):
index = self._list_widget.moveCursor(
QAbstractItemView.MoveUp, Qt.NoModifier
)
elif shorcut.key() == QKeySequence(Qt.Key_Down):
index = self._list_widget.moveCursor(
QAbstractItemView.MoveDown, Qt.NoModifier
)
if index.isValid():
self._list_widget.setCurrentIndex(index)