簡體   English   中英

在Qt 4中無法在eventFilter中檢測到多個按鍵

[英]Cannot detect multiple keypresses in eventFilter in Qt 4

我試圖了解Qt中的事件過濾機制。 為此,我已經將QLineEdit子類化,並嘗試在實際的QLineEdit之前捕獲任何按鍵。 我編寫的代碼(主要是從Qt文檔粘貼)部分有效:如果我按任意一個鍵,QLineEdit正確地說“Ate key press LETTER”。

如果我按下Option鍵(我在Mac上)並按下,比如說“S”,我正確地按“Ate鍵按∫”; 但是,如果我在按住Option鍵的同時再次按下“S”,則QLineEdit會顯示“Ate鍵按∫∫”,這是我無法解釋的。 看起來第二次(和后續)按鍵“S”不是QKeyEvent或QShortcutEvent並直接傳遞給實際的小部件但是,它是什么類型的事件?

更復雜的是,如果在按住Option鍵的同時按下“S”以外的鍵,結果會根據哪個鍵而變化。 例如,對於鍵序列Option + {S,D,F,G,H},QLineEdit讀取“Ate鍵按下∫∂ƒ™”。 但是,如果我繼續按下“J”,那么QLineEdit只讀取“Ate keypress¶”。

任何人都可以復制這種行為,更好的是,解釋一下嗎? 謝謝大家。

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

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

那里有很多不尋常的東西。

首先,事件過濾器旨在允許QObject接收並可選地響應用於另一個QObject的事件。 你在做什么,尤其是這一行:

 this->installEventFilter (this);

基本上是將窗口小部件的事件重定向到自身。 這與功能的設計工作方式不一致,並不能真實反映您將如何在實際項目中使用事件過濾。 當這與你非常強烈的活動結合時,你實際上是打破了小部件。 例如,修改鍵按下作為QKeyEvent傳遞,因此通過在eventfilter函數中使用它們,您可能會拋棄快捷方式處理。

您可能無法獲得QShortcut事件的幾個原因。 我沒有看到任何QShortcut對象被附加。 在你做之前我不希望得到任何QShortcutEvent事件。 此外,我認為它們是與QMenus一起使用的,而不是在所有小部件中獲取修飾符+鍵序列的通用方法。 您通常會使用QKeyEvent :: modifiers()來執行此操作。

此外,通過過濾shortcutoverride事件並將它們作為關鍵事件投射,目前尚不清楚您要做什么。

根據文檔,keyEvent-> text()對於修飾鍵是空的,因此可以解釋字符...在Windows上它顯示為空白。

事件過濾器非常方便,非常適合保持松散耦合和高度可重用性。 這是一個例子,在您學習時可能是一個更好的起點:

main.cpp中

#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();
}

您也可以通過這種方式吞下鍵和鍵+修飾符組合。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM