在 Qt 5 中,假设有以下自定义小部件:
class QMeow final :
public QWidget
{
public:
explicit QMeow()
{
this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
this->setFocusPolicy(Qt::StrongFocus);
}
protected:
void keyPressEvent(QKeyEvent * const event) override
{
_s = !_s;
this->update();
QWidget::keyPressEvent(event);
}
void paintEvent(QPaintEvent *) override
{
QPainter painter {this};
painter.fillRect(this->rect(), QColor {_s ? "red" : "blue"});
}
private:
bool _s = false;
};
当按下任意键时,此小部件的实例会在红色和蓝色之间更改其背景颜色。
现在,让我们创建一个窗口并添加 aQLineEdit
和 a ,并使用快捷键AQMeow
设置操作:
QApplication app {argc, argv};
QWidget window;
QVBoxLayout layout {&window};
layout.addWidget(new QLineEdit);
layout.addWidget(new QMeow);
QAction action {"hello"};
action.setShortcut(Qt::Key_A);
window.addAction(&action);
window.show();
app.exec();
如果您尝试这样做,您会注意到:
- 当
QLineEdit
小部件获得焦点时,它会处理所有键,包括小写A,并将其添加到渲染的文本中。 - 当
QMeow
小部件获得焦点时,它会处理除小写A之外的所有键,这表明操作会处理它。
如何QMeow::keyPressEvent()
调用任何键,包括操作快捷键,例如QLineEdit
?
我尝试了QWidget::grabKeyboard()
不同的焦点策略,但qlineedit.cpp
没有成功。
Qt 中的文本输入小部件通常使用内部“文本控件”,该控件用作任何与文本相关的方面(包括键盘输入)的“代理”。
每当聚焦的小部件可能触发对当前上下文有效的快捷方式时,它总是会收到特殊
ShortcutOverride
事件(QKeyEvent)。请参阅相关文档
QEvent::ShortcutOverride
:同样, QKeyEvent文档的相关部分:
这正是文本输入小部件所做的:它们覆盖
event()
(QLineEdit::event()
) 并将ShortcutOverride
事件发送到内部文本控制对象 (QWidgetLineControl::processShortcutOverrideEvent()
),其中包含以下内容:由于标准字母数字键位于下方
Qt::Key_Escape
(0x01000000
,并且Qt::Key
枚举大多使用标准 ASCII 计数,字母大写),这意味着如果它们没有修饰符,则使用此类键的快捷键始终被接受,Shift在数字键盘。结果是它们接受快捷方式,防止传播到父级,然后父级将被“转换”为标准KeyPress
并最终发送到keyPressEvent()
处理程序。然后,解决方案是覆盖
event()
、检查ShortcutOverride
事件并接受它(假设您确实想要接受此类按键)。