简体   繁体   中英

How we Change focus from QLineEdit to QListWidget by Down_arrow?

In PyQt5, How to change focus from QLineEdit to QListWidget, If I press Down arrow from QLineEdit? And vice Versa

The simplest solution is to get keyboard events, either by subclassing the line edit and override the keyPressEvent or by using an event filter, and set the focus if the key event is a Qt.Key_Down .

Subclassing

In this case, we use a subclass and a custom signal, whenever the down key is pressed it emits the signal, which is connected to setFocus() in the main class.

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)

Event filtering

Using an event filter allows us to avoid unnecessary subclassing, since we only need it for this specific case. We filter the key events and check if the key is correct, then set the focus accordingly.

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)

Note that in both cases I didn't consider the possibility of a QCompleter, which uses arrow keys to select the possible completions.

For many apps, a QMainWidget is the parent widget and is subclassed. So one of the easiest things to do is to override the keyPressed or keyReleased event. But it's important to make a super call in your event to release it to other normal behaviors. So in code below, the super call in the keyRelease method allows for the normal tab functionality for switching focus to also work.

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_())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM