有隐藏项目时关注下一个 QListWidget 项目

Posted

技术标签:

【中文标题】有隐藏项目时关注下一个 QListWidget 项目【英文标题】:Focusing on the next QListWidget item while there are hidden items 【发布时间】:2020-11-03 01:48:16 【问题描述】:

在谈论我的问题之前,我想先谈谈我想做什么。

我希望带有我在QLineEdit 中写的单词的结果出现在QListWidget 中。 我想用键盘关注结果。

如果我用鼠标单击 Qlistwidget 并在那里聚焦,即使有隐藏项目,我也可以用键盘(上/下箭头键)聚焦下一个项目。系统自动完成,无需编写任何代码。

但我想在不失去对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_())

【问题讨论】:

【参考方案1】:

更优雅的解决方案是使用 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)

【讨论】:

以上是关于有隐藏项目时关注下一个 QListWidget 项目的主要内容,如果未能解决你的问题,请参考以下文章

Python:如何在 PyQt 中查询 QListWidget 中的多个选定项

在PyQt5中的QTreeWidget和QListWidget之间拖动项目?

PyQt:如何获得大部分 QListWidget

在单击+拖动时禁用 QListWidget 中的自动选择项目

QListWidget 中的项目在重新排序后变为不可见

如何控制 QListWidget 选择