那里发生了很多不寻常的事情。
首先,事件过滤器旨在允许 QObject 接收并选择性地对用于另一个 QObject 的事件作出反应。你在做什么,尤其是这一行:
this->installEventFilter (this);
基本上是将小部件的事件重定向到自身。这与该功能的设计方式不一致,也不能真正反映您将如何在实际项目中使用事件过滤。当这与您非常强大的事件消耗相结合时,您实际上是在破坏小部件。例如,修饰键按下是作为 QKeyEvent 传递的,因此通过在 eventfilter 函数中使用它们,您可能会丢弃快捷方式处理。
您可能没有收到 QShortcut 事件的几个原因。我没有看到任何 QShortcut 对象被附加。在你这样做之前,我不希望得到任何 QShortcutEvent 事件。另外,我相信它们旨在与 QMenus 一起使用,而不是作为在所有小部件中获取修饰符+键序列的通用方式。您通常会使用 QKeyEvent::modifiers() 来做到这一点。
此外,还不清楚您通过过滤快捷方式覆盖事件并将它们转换为键事件来尝试做什么。
根据文档,对于修饰键,keyEvent->text() 将为空,因此可以解释字符...在 Windows 上它显示为空白。
不过,事件过滤器非常方便,并且非常适合保持松散耦合和高度可重用。下面的示例可能是您学习时更好的起点:
主文件
#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();
}
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
customlineedit.cpp
#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;
}
}
编辑:所以我从评论中看到您正在尝试添加 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();
}
您也可以通过这种方式吞下键和键+修饰符组合。