如何让自定义QWidget接收所有按键事件,甚至全局操作的快捷方式?

问题描述 投票:0回答:1

在 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;
};

按下任意键时,此小部件的实例会在红色和蓝色之间更改其背景颜色。

现在,让我们创建一个窗口并添加一个

QLineEdit
以及一个
QMeow
,同时使用快捷键A设置一个动作:

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 qt5 qwidget
1个回答
0
投票
Qt 中的文本输入小部件通常使用内部“文本控件”,该控件用作任何与文本相关的方面(包括键盘输入)的“代理”。

只要聚焦的小部件可能触发对当前上下文有效的快捷方式,它总是会收到特殊的

ShortcutOverride

 事件(QKeyEvent)。

参见相关文档

QEvent::ShortcutOverride


子级中的按键,用于覆盖快捷键处理(

QKeyEvent)。当快捷方式即将触发时,ShortcutOverride

 会发送到活动窗口。这允许客户端(例如小部件)通过接受事件来发出信号,表明它们将自行处理快捷方式。如果接受快捷方式覆盖,则事件将作为正常按键传递到焦点小部件。否则,它会触发快捷操作(如果存在)。

同样,

QKeyEvent文档的相关部分:

对于 QEvent::ShortcutOverride 接收者需要显式接受事件才能触发覆盖。对按键事件调用ignore()会将其传播到父窗口小部件。该事件沿着父窗口小部件链向上传播,直到窗口小部件接受它或事件过滤器消耗它。

这正是文本输入小部件所做的:它们覆盖

event()

 并将 
ShortcutOverride
 事件发送到内部文本控制对象,其中包含以下内容:

... } else if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier || ke->modifiers() == Qt::KeypadModifier) { if (ke->key() < Qt::Key_Escape) { if (!isReadOnly()) ke->accept();
由于标准字母数字键低于 

Qt::Key_Escape

 (
0x01000000
),这意味着如果这些键没有修饰符、使用 
Shift 或在数字键盘内按下,则始终接受使用此类键的快捷键。结果是它们接受快捷方式,防止传播到父级,然后父级将被“转换”为标准KeyPress
并最终发送到
keyPressEvent()
处理程序。

解决方案是覆盖

event()

,检查 
ShortcutOverride
 事件并接受它(假设您
do想要接受此类按键)。

© www.soinside.com 2019 - 2024. All rights reserved.