Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 无法在Qt 4中的eventFilter中检测到多个按键_C++_Qt_Event Handling - Fatal编程技术网

C++ 无法在Qt 4中的eventFilter中检测到多个按键

C++ 无法在Qt 4中的eventFilter中检测到多个按键,c++,qt,event-handling,C++,Qt,Event Handling,我试图理解Qt中的事件过滤机制。为此,我将QLineEdit子类化,并尝试在实际的QLineEdit之前捕获任何按键。我所写的代码(大部分是从Qt文档中粘贴的)部分有效:如果我按任意一个键,QLineEdit会正确地显示“Ate按键字母” 如果我按下选项键(我在Mac电脑上)并按下,说“S”,我正确地得到“Ate按键”∫"; 但是,如果我在按住Option键的同时再次按下“S”,QLineEdit将显示“Ate键按下”∫∫,我无法解释。看起来第二次(以及随后)按“S”键不是QKeyEvent或Q

我试图理解Qt中的事件过滤机制。为此,我将QLineEdit子类化,并尝试在实际的QLineEdit之前捕获任何按键。我所写的代码(大部分是从Qt文档中粘贴的)部分有效:如果我按任意一个键,QLineEdit会正确地显示“Ate按键字母”

如果我按下选项键(我在Mac电脑上)并按下,说“S”,我正确地得到“Ate按键”∫"; 但是,如果我在按住Option键的同时再次按下“S”,QLineEdit将显示“Ate键按下”∫∫,我无法解释。看起来第二次(以及随后)按“S”键不是QKeyEvent或QShortcutEvent,而是直接传递到实际的小部件,但它是什么类型的事件

更复杂的是,如果在按住Option键的同时按下“S”以外的键,则结果会因键的不同而不同。例如,对于键序列Option+{S,D,F,G,H},QLineEdit会显示“Ate key press”∫∂ƒ™。但是,如果我继续按“J”,则QLineEdit仅显示“Ate按键”

有人可以复制这种行为,更好的是,解释它吗?提前谢谢大家

main.cpp

#include <QApplication>
#include "customlineedit.h"

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    CustomLineEdit w;
    w.show();
    return a.exec();
}
#包括
#包括“customlineedit.h”
int main(int argc,char*argv[]){
质量保证申请a(argc、argv);
自定义行编辑w;
w、 show();
返回a.exec();
}
customlineedit.h

#ifndef CUSTOMLINEEDIT_H
#define CUSTOMLINEEDIT_H

#include <QLineEdit>

class CustomLineEdit : public QLineEdit
{
    Q_OBJECT
public:
    explicit CustomLineEdit(QWidget *parent = 0);
    virtual bool eventFilter(QObject *watched, QEvent *event);
};

#endif // CUSTOMLINEEDIT_H
#ifndef CUSTOMLINEEDIT_H
#define CUSTOMLINEEDIT_H

#include <QLineEdit>

class CustomLineEdit : public QLineEdit
{
    Q_OBJECT
public:
    explicit CustomLineEdit(QWidget *parent = 0);
    virtual bool eventFilter(QObject *watched, QEvent *event);
};

#endif // CUSTOMLINEEDIT_H
\ifndef CUSTOMLINEEDIT\u H
#定义CUSTOMLINEEDIT_H
#包括
类CustomLineEdit:公共QLineEdit
{
Q_对象
公众:
显式CustomLineEdit(QWidget*parent=0);
虚拟布尔事件过滤器(QObject*监视,QEvent*事件);
};
#endif//CUSTOMLINEEDIT\u H
customlineedit.cpp

#include "customlineedit.h"
#include <QKeyEvent>

CustomLineEdit::CustomLineEdit(QWidget *parent) :
    QLineEdit(parent)
{
    this->installEventFilter (this);
}

bool CustomLineEdit::eventFilter (QObject *watched, QEvent *event)
{
    if (event->type () == QEvent::KeyPress
        || event->type () == QEvent::ShortcutOverride) {
        QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
        this->setText("Ate key press " + keyEvent->text());
        return true;
    } else if (event->type () == QEvent::Shortcut) {
        this->setText ("Shortcut event");
        return true;
    } else {
        return false;
    }
}
#include <QtGui/QApplication>

#include "customlineedit.h"

#include <QWidget>
#include <QLineEdit>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QWidget w;
    QLineEdit *le1 = new QLineEdit( &w );
    le1->move( 4, 4 );
    le1->setMinimumWidth( 200 );
    CustomLineEdit *le2 = new CustomLineEdit( &w );
    le2->move( 4, 35 );
    le2->setMinimumWidth( 200 );

    le1->installEventFilter (le2);

    w.setMinimumWidth( 260);
    w.show();

    return a.exec();
}
#include "customlineedit.h"

#include<QShortcutEvent>

CustomLineEdit::CustomLineEdit(QWidget *parent) :
    QLineEdit(parent)
{
}


bool CustomLineEdit::eventFilter (QObject *watched, QEvent *event)
{
    if (event->type() == QEvent::KeyPress) {
        QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
        this->setText("QKeyEvent: " + QString::number(keyEvent->modifiers() ) +" / "+ QString::number(keyEvent->key()) );
        return false;
    } else if (event->type () == QEvent::Shortcut) { //you shouldn't see these here...
        QShortcutEvent *shrtcutEvent = static_cast<QShortcutEvent*>(event);
        this->setText ("Shortcut event: " + shrtcutEvent->key().toString() );
        return false;
    } else {
        return false;
    }
}
#包括“customlineedit.h”
#包括
CustomLineEdit::CustomLineEdit(QWidget*父项):
QLineEdit(父级)
{
此->installEventFilter(此);
}
bool CustomLineEdit::eventFilter(QObject*监视,QEvent*事件)
{
如果(事件->类型()==QEvent::按键
||事件->类型()==QEvent::ShortcutOverride){
QKeyEvent*keyEvent=静态广播(事件);
此->设置文本(“Ate按键”+keyEvent->文本());
返回true;
}else if(事件->类型()==QEvent::快捷方式){
此->设置文本(“快捷方式事件”);
返回true;
}否则{
返回false;
}
}

那里发生了很多不寻常的事情

首先,事件筛选器用于允许QoObject接收并选择性地对另一个QoObject的事件做出反应。您正在做的事情,尤其是这一行:

 this->installEventFilter (this);
基本上是将小部件的事件重定向到自身。这与功能设计的工作方式不一致,也不能真正反映您将如何在实际项目中使用事件过滤。当这与您非常强烈的事件吞噬相结合时,您基本上破坏了小部件。例如,按修改器键会导致这是一个QKeyEvent,因此在eventfilter函数中使用它们很可能会导致快捷方式处理失败

您可能无法获取QShortcut事件的几个原因。我看不到任何QShortcut对象被附加。在您获取QShortcutEvent事件之前,我不希望获取任何QShortcutEvent事件。此外,我相信它们是用于QMenus的,而不是作为在所有小部件中获取修饰符+键序列的通用方法。您通常会使用QKeyEvent::modifiers()这样做

此外,还不清楚通过过滤shortcutoverride事件并将其转换为keyevents,您试图做什么

根据文档,修改键的keyEvent->text()将为空,这可能解释了它在窗口上显示为空的字符

不过,事件过滤器非常方便,非常适合保持松散耦合和高度可重用性。下面的示例可能是您学习的更好起点:

main.cpp

#include "customlineedit.h"
#include <QKeyEvent>

CustomLineEdit::CustomLineEdit(QWidget *parent) :
    QLineEdit(parent)
{
    this->installEventFilter (this);
}

bool CustomLineEdit::eventFilter (QObject *watched, QEvent *event)
{
    if (event->type () == QEvent::KeyPress
        || event->type () == QEvent::ShortcutOverride) {
        QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
        this->setText("Ate key press " + keyEvent->text());
        return true;
    } else if (event->type () == QEvent::Shortcut) {
        this->setText ("Shortcut event");
        return true;
    } else {
        return false;
    }
}
#include <QtGui/QApplication>

#include "customlineedit.h"

#include <QWidget>
#include <QLineEdit>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QWidget w;
    QLineEdit *le1 = new QLineEdit( &w );
    le1->move( 4, 4 );
    le1->setMinimumWidth( 200 );
    CustomLineEdit *le2 = new CustomLineEdit( &w );
    le2->move( 4, 35 );
    le2->setMinimumWidth( 200 );

    le1->installEventFilter (le2);

    w.setMinimumWidth( 260);
    w.show();

    return a.exec();
}
#include "customlineedit.h"

#include<QShortcutEvent>

CustomLineEdit::CustomLineEdit(QWidget *parent) :
    QLineEdit(parent)
{
}


bool CustomLineEdit::eventFilter (QObject *watched, QEvent *event)
{
    if (event->type() == QEvent::KeyPress) {
        QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
        this->setText("QKeyEvent: " + QString::number(keyEvent->modifiers() ) +" / "+ QString::number(keyEvent->key()) );
        return false;
    } else if (event->type () == QEvent::Shortcut) { //you shouldn't see these here...
        QShortcutEvent *shrtcutEvent = static_cast<QShortcutEvent*>(event);
        this->setText ("Shortcut event: " + shrtcutEvent->key().toString() );
        return false;
    } else {
        return false;
    }
}
#包括
#包括“customlineedit.h”
#包括
#包括
int main(int argc,char*argv[])
{
质量保证申请a(argc、argv);
qw;
QLineEdit*le1=新的QLineEdit(&w);
le1->移动(4,4);
le1->设置最小宽度(200);
CustomLineEdit*le2=新的CustomLineEdit(&w);
le2->move(4,35);
le2->设置最小宽度(200);
le1->installEventFilter(le2);
w、 设置最小宽度(260);
w、 show();
返回a.exec();
}
customlineedit.h

#ifndef CUSTOMLINEEDIT_H
#define CUSTOMLINEEDIT_H

#include <QLineEdit>

class CustomLineEdit : public QLineEdit
{
    Q_OBJECT
public:
    explicit CustomLineEdit(QWidget *parent = 0);
    virtual bool eventFilter(QObject *watched, QEvent *event);
};

#endif // CUSTOMLINEEDIT_H
#ifndef CUSTOMLINEEDIT_H
#define CUSTOMLINEEDIT_H

#include <QLineEdit>

class CustomLineEdit : public QLineEdit
{
    Q_OBJECT
public:
    explicit CustomLineEdit(QWidget *parent = 0);
    virtual bool eventFilter(QObject *watched, QEvent *event);
};

#endif // CUSTOMLINEEDIT_H
\ifndef CUSTOMLINEEDIT\u H
#定义CUSTOMLINEEDIT_H
#包括
类CustomLineEdit:公共QLineEdit
{
Q_对象
公众:
显式CustomLineEdit(QWidget*parent=0);
虚拟布尔事件过滤器(QObject*监视,QEvent*事件);
};
#endif//CUSTOMLINEEDIT\u H
customlineedit.cpp

#include "customlineedit.h"
#include <QKeyEvent>

CustomLineEdit::CustomLineEdit(QWidget *parent) :
    QLineEdit(parent)
{
    this->installEventFilter (this);
}

bool CustomLineEdit::eventFilter (QObject *watched, QEvent *event)
{
    if (event->type () == QEvent::KeyPress
        || event->type () == QEvent::ShortcutOverride) {
        QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
        this->setText("Ate key press " + keyEvent->text());
        return true;
    } else if (event->type () == QEvent::Shortcut) {
        this->setText ("Shortcut event");
        return true;
    } else {
        return false;
    }
}
#include <QtGui/QApplication>

#include "customlineedit.h"

#include <QWidget>
#include <QLineEdit>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QWidget w;
    QLineEdit *le1 = new QLineEdit( &w );
    le1->move( 4, 4 );
    le1->setMinimumWidth( 200 );
    CustomLineEdit *le2 = new CustomLineEdit( &w );
    le2->move( 4, 35 );
    le2->setMinimumWidth( 200 );

    le1->installEventFilter (le2);

    w.setMinimumWidth( 260);
    w.show();

    return a.exec();
}
#include "customlineedit.h"

#include<QShortcutEvent>

CustomLineEdit::CustomLineEdit(QWidget *parent) :
    QLineEdit(parent)
{
}


bool CustomLineEdit::eventFilter (QObject *watched, QEvent *event)
{
    if (event->type() == QEvent::KeyPress) {
        QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
        this->setText("QKeyEvent: " + QString::number(keyEvent->modifiers() ) +" / "+ QString::number(keyEvent->key()) );
        return false;
    } else if (event->type () == QEvent::Shortcut) { //you shouldn't see these here...
        QShortcutEvent *shrtcutEvent = static_cast<QShortcutEvent*>(event);
        this->setText ("Shortcut event: " + shrtcutEvent->key().toString() );
        return false;
    } else {
        return false;
    }
}
#包括“customlineedit.h”
#包括
CustomLineEdit::CustomLineEdit(QWidget*父项):
QLineEdit(父级)
{
}
bool CustomLineEdit::eventFilter(QObject*监视,QEvent*事件)
{
如果(事件->类型()==QEvent::按键){
QKeyEvent*keyEvent=静态广播(事件);
这->setText(“QKeyEvent:+QString::number(keyEvent->modifiers())+”/“+QString::number(keyEvent->key());
返回false;
}否则如果(event->type()==QEvent::Shortcut){//您不应该在这里看到这些。。。
QShortcutEvent*shrtcutEvent=static_cast(事件);
此->设置文本(“快捷方式事件:+shrtcutEvent->key().toString());
返回false;
}否则{
返回false;
}
}
编辑:因此,我从评论中看到,您正在尝试添加Emacs样式的自定义快捷方式。这是一个好主意!以下是我在不使用事件筛选的情况下的做法:

#include <QtGui/QApplication>

#include <QLineEdit>
#include <QKeyEvent>
#include <QDebug>


class LineEditEmacs : public QLineEdit
{
    void keyPressEvent( QKeyEvent* event )
    {
        //qDebug()<< QString::number( event->key(), 16 ).toUpper();
        switch ( event->key() )
        {
        case Qt::Key_Up:
            { undo(); return; }
        case Qt::Key_Down:
            { redo(); return; }
        case Qt::Key_Minus: //shift+underscore
            if( (event->modifiers() & Qt::ShiftModifier) == Qt::ShiftModifier ) { undo(); return; }

        case Qt::Key_U:
            if( (event->modifiers() & Qt::ControlModifier) == Qt::ControlModifier ) {
                SetSelectionToCase( true );
                return;
            }
        case Qt::Key_L:
            if( (event->modifiers() & Qt::ControlModifier) == Qt::ControlModifier ) {
                SetSelectionToCase( false );
                return;
            }

        default: 
            break;
        }
        QLineEdit::keyPressEvent( event );
    }

    void SetSelectionToCase( bool Upper )
    {
        if( !hasSelectedText() )
            return;

        QString s = selectedText();
        int iPreviousCursorPos = cursorPosition();
        del();
        QString su = Upper? s.toUpper() : s.toLower();
        insert( su );
        int iNewCursorPos = cursorPosition();

        //restore selection
        if( iPreviousCursorPos < iNewCursorPos )
            cursorBackward( true, su.length() );
        else if( iPreviousCursorPos == iNewCursorPos )
            setSelection( iPreviousCursorPos-su.length(), su.length() );
    }



};


int main( int argc, char *argv[] )
{
    QApplication a( argc, argv );
    LineEditEmacs w;
    w.show();
    return a.exec();
}
#包括
#包括
#包括
#包括
类LineEditEmacs:公共QLineEdit
{
无效按键事件(QKeyEvent*事件)
{
//qDebug()键(),16).toUpper();
开关(事件->键())
{
案例Qt::键向上: