【问题标题】:QShortCut and QSpinBox conflictQShortCut 和 QSpinBox 冲突
【发布时间】:2011-04-12 18:18:49
【问题描述】:

如果我使用自己的快捷方式,我正在编写一个应用程序。它看起来像这样:

myShortcut= new QShortcut(Qt::SHIFT + Qt::Key_B,this);
connect(myShortcut, SIGNAL(activated()), this, SLOT(setCameraBack()));

我在主窗口小部件的构造函数中定义了它,它工作正常,直到我单击也位于主窗口小部件上的旋转框按钮之一。之后,我的快捷方式停止工作,直到我单击按钮或复选框才起作用。当我这样做时,一切都很好。我想补充一点,在我单击旋转框后,它似乎是“活动的”(因为光标仍在其上“闪烁”),直到我单击其他按钮之一。你知道有什么问题吗?是某种过程或事件问题吗?感谢所有答案 ~马尔罗克

【问题讨论】:

    标签: qt qt4


    【解决方案1】:

    Qt 的“监听”快捷方式 快捷方式的父级时的事件循环 小部件正在接收事件。

    当 QSpinBox 有keyboard focus 时,则 QShortcut 对象的父对象不再接收事件。因此,在从 QSpinBox 中删除 keyboard focus 之前,该快捷方式不起作用。您可以通过将 Qt::WidgetWithChildrenShortcut or Qt::ApplicationShortcut 传递给 QShortcut 的 QShortcut::setContext 方法来更改此行为。

    【讨论】:

    • 感谢您的回答。你可能知道如何解决这个问题?我的意思是如何在每次“点击”后自动从 QSpinBox 中删除键盘焦点?
    • @Marwroc 我更新了答案。你试过QShortcut::setContext了吗?
    • 是的,我已经尝试了这两个选项,但仍然无法正常工作;/ 我阅读了一些有关 setFocusPolicy() 的内容,但我不确定如何使用它以及是否是解决方案。跨度>
    • @Marwroc 你必须使用 Shift-B 吗? Ctrl-B 或 Alt-B 可能会起作用。
    【解决方案2】:

    在激活快捷方式之前,会为焦点小部件提供一个 ShortcutOverride 事件。如果该事件被接受,则将按键事件传递给小部件并且不会激活快捷方式。

    来源:https://wiki.qt.io/ShortcutOverride

    看Qt源码

    QAbstractSpinBox::event(QEvent *event)
    {
        Q_D(QAbstractSpinBox);
        switch (event->type()) {
        ...
        case QEvent::ShortcutOverride:
            if (d->edit->event(event))
                return true;
            break;
        ...
        }
        return QWidget::event(event);
    }
    

    QAbstractSpinBox 允许内部编辑接受事件。 QLineEdit 遵循 QLineControl。来自 qt/src/gui/widgets/qlinecontrol.cpp

        case QEvent::ShortcutOverride:{
            if (isReadOnly())
                return false;
            QKeyEvent* ke = static_cast<QKeyEvent*>(ev);
            if (ke == QKeySequence::Copy
                || ke == QKeySequence::Paste
                || ke == QKeySequence::Cut
                || ke == QKeySequence::Redo
                || ke == QKeySequence::Undo
                || ke == QKeySequence::MoveToNextWord
                || ke == QKeySequence::MoveToPreviousWord
                || ke == QKeySequence::MoveToStartOfDocument
                || ke == QKeySequence::MoveToEndOfDocument
                || ke == QKeySequence::SelectNextWord
                || ke == QKeySequence::SelectPreviousWord
                || ke == QKeySequence::SelectStartOfLine
                || ke == QKeySequence::SelectEndOfLine
                || ke == QKeySequence::SelectStartOfBlock
                || ke == QKeySequence::SelectEndOfBlock
                || ke == QKeySequence::SelectStartOfDocument
                || ke == QKeySequence::SelectAll
                || ke == QKeySequence::SelectEndOfDocument) {
                ke->accept();
            } else if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier
                       || ke->modifiers() == Qt::KeypadModifier) {
                if (ke->key() < Qt::Key_Escape) {
                    ke->accept();
                } else {
                    switch (ke->key()) {
                    case Qt::Key_Delete:
                    case Qt::Key_Home:
                    case Qt::Key_End:
                    case Qt::Key_Backspace:
                    case Qt::Key_Left:
                    case Qt::Key_Right:
                        ke->accept();
                    default:
                        break;
                    }
                }
            }
        }
    

    如果没有同时按下控制键,则此代码接受大多数键。

    所以最简单的解决方案是更改快捷方式以包含控件修饰符。

    或者,您可以子类化旋转框并覆盖事件函数

    bool MySpinBox::event(QEvent *event)
    {
        if( event->type() == QEvent::ShortcutOverride && !isReadOnly() )
        {
            QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
            // Ignore 'B' shortcuts
            if( keyEvent->key() == Qt::Key_B )
            {
                Q_ASSERT( !event->isAccepted() );
                return true;
        }
        return QSpinBox::event(event);
    }
    

    【讨论】:

      【解决方案3】:

      你试过MySpinBox -&gt; setFocusPolicy (Qt::NoFocus)吗?

      【讨论】:

      • 谢谢,它可以工作,但现在的问题是我无法在 QSpinBox 中输入任何内容,只需单击即可。我的 QSpinBox 的范围是从 0 到 500,所以打字是非常必要的;/
      • 我找到了解决方案。我在 main_widget 上使用了 setFocusPolicy (Qt::ClickFocus),现在它工作正常。再次感谢您的帮助;)
      猜你喜欢
      • 2019-08-27
      • 2012-09-10
      • 2012-08-24
      • 2021-03-06
      • 2015-04-06
      • 2012-04-07
      • 2015-12-10
      • 2016-12-13
      • 2016-04-05
      相关资源
      最近更新 更多