«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)