«Shift+Return» QShortcut в PyQt QPlainTextEdit

Я пытаюсь написать небольшую консоль командной строки в PyQt, похожую на Jupyter Qtconsole . В качестве простого первого шага я хотел бы иметь возможность выполнять команды при нажатии комбинации клавиш «Shift+Return». В приведенном ниже примере кода показано, что существует определенное взаимодействие между «Shift+Return» в QPlainTextEdit, поэтому оно ведет себя иначе, чем случайное сочетание клавиш, например «Ctrl+k». При использовании «Shift+Return» приведенный ниже код не печатает «Bar» при нажатии «Shift+Return», тогда как «Ctrl+k» печатает «Foo».

Вопросы QShortcut и QKeySequence с Shift+Return в элементе QPlainTextEdit аналогичны и предлагают решение, а QPlainTextEdit - изменение поведения Shift+Return относятся к одной и той же теме и предлагают схожие решения. Но мне любопытно, почему это вообще проблема. Почему «Shirt+Return» не работает с QPlainTextEdit?

      import PyQt6.QtWidgets as qw
import PyQt6.QtGui as qg
import PyQt6.QtCore as qc



class Console(qw.QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("My App")
        self.qptext = qw.QPlainTextEdit() 
        
        self.shortcut1 = qg.QShortcut(
            qg.QKeySequence('Ctrl+k'),
            self)
        self.shortcut1.activated.connect(lambda : print("Foo"))
        self.shortcut2 = qg.QShortcut(
            qg.QKeySequence('Shift+Return'),
            self)
        self.shortcut2.activated.connect(lambda : print("Bar"))

        self.setCentralWidget(self.qptext)


app = qw.QApplication([])

window = Console()
window.show() 

app.exec()

1 ответ

Он игнорируется, поскольку текстовый редактор уже использует ярлык: если вы посмотрите на стандартный список ярлыков QKeySequence, вы увидите, что в Windows и Linux Shift+ EnterсоответствуетInsertLineSeparatorпоследовательность.

Обратите внимание: хотя в списке показан только Enterключ, на самом деле включается и комбинация Return(см. исходники QPlatformTheme).

Разница со стандартным Enter/Return не актуальна для QPlainTextEdit, но если бы вы использовали QTextEdit (который использует тот же закрытый элемент управления для взаимодействия с текстом), это было бы иначе: Enter/Return создает новый абзац (новый<p></p>блокировать при экспорте в HTML), а использование модификатора Shift приведет к разрыву текущей строки (<br>) в том же абзаце.

Фактически, если вы измените ярлык для использованияEnter, вы увидите, что это будет тот же QKeySequence:

          self.shortcut2 = qw.QShortcut(
        qg.QKeySequence('Shift+Enter'),
        self)
    print(self.shortcut2.key() == qg.QKeySequence(qg.QKeySequence.InsertLineSeparator))

Когда виджет принимает событие клавиатуры, оно не передается родительскому элементу (или, в случае сочетаний клавиш, контексту), поэтому сочетание клавиш вообще не срабатывает.

Если вы хотите переопределить это поведение, потому что эта комбинация клавиш вас не интересует, просто установите фильтр событий в виджете и игнорируйте событие:

              ...
        self.qptext.installEventFilter(self)


    def eventFilter(self, obj, event):
        if (
            event.type() in (event.Type.KeyPress, event.Type.ShortcutOverride)
            and event.key() == qc.Qt.Key.Key_Return
            and event.modifiers() == qc.Qt.KeyboardModifier.ShiftModifier
        ):
            event.ignore()
            return True
        return super().eventFilter(obj, event)
Другие вопросы по тегам