Reputation: 653
In PyQt5, How to change focus from QLineEdit to QListWidget, If I press Down arrow from QLineEdit ? And vice Versa
Upvotes: 1
Views: 1218
Reputation: 5835
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_())
Upvotes: 1
Reputation: 48489
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
.
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)
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.
Upvotes: 2