WoaItsBren
WoaItsBren

Reputation: 97

Move focus to another widget when the return or right arrow key is pressed?

I have a Qt widget that looks like this:

class launchiiwidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        layout = QtWidgets.QVBoxLayout(self)

        self.textbox = QtWidgets.QTextEdit(self)
        self.textbox.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
        self.textbox.setAlignment(QtCore.Qt.AlignCenter)   
        self.textbox.setFixedSize(QtCore.QSize(600, 100))
        self.textbox.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.textbox.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        
        layout.addWidget(self.textbox)

        font = self.textbox.font()
        font.setPointSize(80)
        self.textbox.setFont(font)

        self.listwidget = QtWidgets.QListWidget(self)
        self.listwidget.addItem("Red")
        self.listwidget.addItem("Blue") 
        layout.addWidget(self.listwidget)

if __name__ == "__main__":
    app = QtWidgets.QApplication([])

    widget = launchiiwidget()
    widget.setWindowFlags(QtCore.Qt.FramelessWindowHint)
    widget.resize(600, 200)
    widget.show()

    sys.exit(app.exec())

How can I make it so when the "return" or "right arrow key" is pressed, focus moves from wherever it is currently to the first item in listwidget? This should also work while being focused inside of textbox, without triggering a newline.

Note: items get dynamically added to listwidget.

Upvotes: 0

Views: 361

Answers (1)

eyllanesc
eyllanesc

Reputation: 244301

A possible solution could be to use QShorcut but because the OP requires "without triggering a newline". So in this case the solution is to implement an eventfilter to the QWindow:

import sys

from PyQt6 import QtCore, QtGui, QtWidgets


class KeyHelper(QtCore.QObject):
    pressed = QtCore.pyqtSignal()

    def __init__(self, window):
        super().__init__(window)
        self._window = window

        self.window.installEventFilter(self)

    @property
    def window(self):
        return self._window

    def eventFilter(self, obj, event):
        if event.type() == QtCore.QEvent.Type.KeyPress:
            if event.key() in (
                QtCore.Qt.Key.Key_Return,
                QtCore.Qt.Key.Key_Enter,
                QtCore.Qt.Key.Key_Right,
            ):
                self.pressed.emit()
                return True
        return super().eventFilter(obj, event)


class Launchiiwidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        self.textbox = QtWidgets.QTextEdit()
        self.textbox.setLineWrapMode(QtWidgets.QTextEdit.LineWrapMode.NoWrap)
        self.textbox.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
        self.textbox.setFixedSize(QtCore.QSize(600, 100))
        self.textbox.setVerticalScrollBarPolicy(
            QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff
        )
        self.textbox.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff
        )

        font = self.textbox.font()
        font.setPointSize(80)
        self.textbox.setFont(font)

        self.listwidget = QtWidgets.QListWidget()
        self.listwidget.addItem("Red")
        self.listwidget.addItem("Blue") 

        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.textbox)
        layout.addWidget(self.listwidget)

    def update_focus(self):
        self.listwidget.setFocus()
        index = self.listwidget.model().index(0, 0)
        if index.isValid():
            self.listwidget.setCurrentIndex(index)


if __name__ == "__main__":
    app = QtWidgets.QApplication([])

    widget = Launchiiwidget()
    widget.setWindowFlags(QtCore.Qt.WindowType.FramelessWindowHint)
    widget.resize(600, 200)
    widget.show()

    key_helper = KeyHelper(widget.windowHandle())
    key_helper.pressed.connect(widget.update_focus)

    sys.exit(app.exec())

Upvotes: 2

Related Questions