Как мы меняем фокус с QLineEdit на QListWidget с помощью стрелки вниз? - PullRequest
1 голос
/ 09 мая 2020

В PyQt5, как изменить фокус с QLineEdit на QListWidget, если я нажму стрелку вниз в QLineEdit? И наоборот

Ответы [ 2 ]

2 голосов
/ 11 мая 2020

Простейшим решением является получение событий клавиатуры либо путем создания подкласса редактирования строки и переопределения keyPressEvent, либо с помощью фильтра событий и установки фокуса, если ключевым событием является Qt.Key_Down.

Создание подкласса

В этом случае мы используем подкласс и настраиваемый сигнал, всякий раз, когда нажимается клавиша «вниз», он излучает сигнал, который связан с setFocus() в основном классе.

class DownKeyEdit(QtWidgets.QLineEdit):
    downKeyPressed = QtCore.pyqtSignal()
    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Down:
            self.downKeyPressed.emit()
            event.accept()
        else:
            super().keyPressEvent(event)


class Test(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        layout = QtWidgets.QVBoxLayout(self)
        self.lineEdit = DownKeyEdit()
        layout.addWidget(self.lineEdit)
        self.listWidget = QtWidgets.QListWidget()
        layout.addWidget(self.listWidget)
        self.listWidget.addItems(['Item {}'.format(i + 1) for i in range(10)])

        self.lineEdit.downKeyPressed.connect(self.listWidget.setFocus)

Фильтрация событий

Использование фильтра событий позволяет нам избежать ненужного подкласса, поскольку он нам нужен только для этого конкретного случая c. Мы фильтруем ключевые события и проверяем правильность ключа, а затем соответственно устанавливаем фокус.

class Test(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        layout = QtWidgets.QVBoxLayout(self)
        self.lineEdit = QtWidgets.QLineEdit()
        layout.addWidget(self.lineEdit)
        self.listWidget = QtWidgets.QListWidget()
        layout.addWidget(self.listWidget)
        self.listWidget.addItems(['Item {}'.format(i + 1) for i in range(10)])

        self.lineEdit.installEventFilter(self)

    def eventFilter(self, source, event):
        if event.type() == QtCore.QEvent.KeyPress and event.key() == QtCore.Qt.Key_Down:
            self.listWidget.setFocus()
            event.accept()
        return super().eventFilter(source, event)

Обратите внимание, что в обоих случаях я не рассматривал возможность QCompleter, который использует клавиши со стрелками для выбора возможные доработки.

1 голос
/ 11 мая 2020

Для многих приложений QMainWidget является родительским виджетом и является подклассом. Поэтому один из самых простых способов - переопределить событие keyPressed или keyReleased. Но важно сделать супер-вызов на вашем мероприятии, чтобы вернуть его к другому нормальному поведению. Таким образом, в приведенном ниже коде супер-вызов в методе keyRelease позволяет также использовать обычные функции вкладки для переключения фокуса.

import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, 
                             QLineEdit, QListWidget)
from PyQt5.QtCore import Qt

class Main(QMainWindow):
    def __init__(self, parent=None):

        super(Main, self).__init__()

        self.lineEdit = QLineEdit(parent=self, objectName='lineEdit')
        self.lineEdit.move(50,50)
        self.listWidget = QListWidget(parent=self, objectName='listWidget')
        self.listWidget.addItem('item1')
        self.listWidget.addItem('item2')
        self.listWidget.setGeometry(50,100, 100, 100)

        self.setGeometry(300, 300, 300, 300)

    def keyReleaseEvent(self, event):
        if self.focusWidget().objectName() == 'lineEdit':
            if event.key() == Qt.Key_Down:
                self.listWidget.setFocus()
        else:
            super().keyPressEvent(event)


app = QApplication(sys.argv)
main = Main(None)

main.show()

sys.exit(app.exec_())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...