Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Using an Eventfilter



  • I am trying to allow the users to double-click into a QLineEdit field and to have some custom function run. I've found that using an eventfilter is the best way to accomplish this...and Im trying to use that, and I'm having trouble putting the QT documentation into the context of my program...So I'm looking for some assistance.

    Again, I'm having some trouble understanding the QT documentation. I understand what the eventfilter does...It will look for the event and it will direct it to do what I need it to...so do I need to do a new EVENTFILTER for every field I want to check for an event, or is event filter a more global setting that can be used for all events that occur on a particular form?

    So in my specific example, I have a QLineEdit field called reserveLineEdit in a form called deptSchedule. Do I need to setup an EVENTFILTER inside the deptSchedule.cpp that is looking for the events occurring on the reserveLineEdit field? Or will EVENTFILTER capture all events within the whole deptSchedule form...then within there, I'll need to set up individual conditions to check for doubleclilck events from each field?



  • https://doc.qt.io/qt-5/qobject.html#installEventFilter

    Check that out. I THINK this is a pretty clear example.

    subclass QObject,
    Make your custom event filter,
    instantiate that filter class,
    installer that filter onto your widget(s)

    I would basically emit a signal when your filter triggers from your event filter class connected to a slot which contains your custom function(s) you want to run.



  • That example is much clearer than what I found. Ill give it a try. Thank you.



  • Ok. So I'm trying the above, and getting an error. I've called my class clickCatcher. The error I get when compiling is "clickCatcher is not a type". The line below where the error is flagged is in deptschedule.cpp
    " ui->reserveLineEdit->installEventFilter(clickCatcher);"

    Here is my code:

    [clickcatcher.h]

    #ifndef CLICKCATCHER_H
    #define CLICKCATCHER_H

    #include <QDialog>
    #include <QtSql>
    #include <QtGui>
    #include "security.h"

    class clickCatcher : public QObject
    {
    Q_OBJECT

    protected:
    // bool eventFilter(QObject *obj, QEvent *event) override;
    bool eventFilter(QObject *obj, QEvent *event) ;

    public:
    explicit clickCatcher(QWidget *parent = 0);
    ~clickCatcher();
    };

    #endif // CLICKCATCHER_H

    [clickCatcher.cpp]

    #include "clickcatcher.h"

    clickCatcher::~clickCatcher()
    {

    }

    bool clickCatcher::eventFilter(QObject *obj, QEvent *event)
    {
    if (event->type() == QEvent::KeyPress)
    {
    QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
    qDebug("Ate key press %d", keyEvent->key());
    return true;
    }
    else
    {
    // standard event processing
    return QObject::eventFilter(obj, event);
    }
    }

    [snippet from deptschedule.cpp]

    .
    .
    .
    clickCatcher *clickCatcher = new clickCatcher(this);
    ui->reserveLineEdit->installEventFilter(clickCatcher);


  • Lifetime Qt Champion

    Hi,

    Did you forgot to include clickcatcher.h in the .cpp files where you use it ?



  • Yes, its there. If I remove clickcatcher.h, it says "clickCatcher is undeclared".

    This message says 'clickCatcher' is not a type.

    And I don't know if something changed since I sent my original message or if I just mis-read it, but the debugger is pointing at the line "clickCatcher *clickCatcher = new clickCatcher(this);" when reporting the error....



  • clickCatcher *clickCatcher = new clickCatcher(this);

    You declare a variable the same name as the class !

    Usely a class name begins with a capital letter.

    Anyway, I don't get the thing to use a event filter to implement a double click ....



  • Well mpergand, you might be on to something.

    I changed:

    clickCatcher *clickCatcher = new clickCatcher(this);
    ui->reserveLineEdit->installEventFilter(clickCatcher);

    To:

    clickCatcher *ClickCatcher = new clickCatcher(this);
    ui->reserveLineEdit->installEventFilter(ClickCatcher);

    and that error message went away. But now I got a new error.

    "Undefined reference to 'clickCatcher::clickCatcher(QWidget*)"



  • And mpergand, are you questioning why I would want to capture a double click on a field, or why I would I use event filter to do that?

    I'm totally open to capturing double click events another way if you have any suggestions....I'm only using the eventfilter because I found a few references to it on-line.

    If your question was why would I want to capture a double-click event on a field...I do it all that time when programming in other languages. A common way I use it is to have the user double-click onto a date field and have the date replaced with todays date.

    In other cases...I like to give users the ability...while looking at a customer sales order, to click on the part number the customer is ordering, and have the part master file pop up so they can see any other part specific information they might be interested in.

    Or maybe double click on an on-hand quantity on screen and pull up all the lot and location detail for that part.

    Its a very useful feature once its working, so that's what I'm trying to accomplish with this question.



  • "Undefined reference to 'clickCatcher::clickCatcher(QWidget*)"

    unconstancy spotted ;)

    Well, you want to add some functionalities to QLineEdit, in OPP we do that by subclassing.
    In your subclass, override mouseDoubleClickEvent(QMouseEvent *event)
    You can do what ever you want from there, call special function, emit a signal, etc.

    Event filters can be powerfull , but look a little hacky for your use case, AMHO.



  • Do you have an example of a subclass that does something like Im trying to do that you could share? Im still stuck on the event filters at the moment and cant seem to get it to work.



  • class MyLineEdit : public QLineEdit
    {
        void mouseDoubleClickEvent(QMouseEvent *event)
        {
        qDebug()<<event;
        }
    
    };
    

    Log:

    QMouseEvent(MouseButtonDblClick, LeftButton, localPos=155,12, screenPos=797,323.082)
    


  • Ok...I haven't used subclass in years...refresh my memory.

    So, in your app, then instead of using QLineEdit for your fields, you use MyLineEdit? Then when you do, your customized logic for mouseDoubleClickEvent takes precedence over what QLineEdit does when it encounters a double click?

    So do you use QT Creator to design your forms? How do you get MyLineEdit to be an option when designing a form?

    And not sure what is meant by Log: in your earlier post?



  • your customized logic for mouseDoubleClickEvent takes precedence over what QLineEdit does when it encounters a double click?

    You can look at some modifier keys, ALT,SHIFT etc
    Try to detect a tripple click (don't know how it works in Qt)

    [edit] obviously, you can call the base method to have the standard behavior:

    QLineEdit::mouseDoubleClickEvent(event);
    

    Maybe it would be simplier to use a context Menu, you can add your actions to the menu return by createStandardContextMenu()

    So do you use QT Creator to design your forms? How do you get MyLineEdit to be an option when designing a form?

    Look at "Promotion" in the Designer doc.

    And not sure what is meant by Log: in your earlier post?

    Logs are the messges you see in the Application output panel in QtCreator.



  • Thanks for the responses. Always wondered about "promotion"...I understand how thats used now, given our discussion.

    I like the "context menu" suggestion. Didn't know that existed, and I could see that being useful for either this situation or something else I might do in the future.

    Out of pure spite at this point, I still need to understand what I'm doing wrong with the event filter. At the end of the day on Friday, through much trial and error, I got my program to a point where I no longer am getting any errors when I compile, but it still doesn't do anything when I double click inside the field!

    I'll be able to work on it again tomorrow, but I'm nearly certain there is still an issue with clickCatcher.cpp. That was my first attempt at creating a program without a UI associated with it. I didn't have any documentation or models to follow, I just removed code that either failed during the compile, or just didn't make sense given no UI exists. Anyone see anything in the CPP i posted earlier that may explain why the "qDebug("Ate key press %d", keyEvent->key());" doesn't fire when start typing in that field? Once I get over that hurdle, with a small change to start capturing the double click event instead of "keypress", I should have what I set out to accomplish in the first place.

    Thanks!!



  • Continuing with MyLineEdit subclass:

    class MyLineEdit : public QLineEdit
    {
        public:
        MyLineEdit(QWidget* parent=nullptr) : QLineEdit(parent)
        {
        installEventFilter(this);
        }
    
        void mouseDoubleClickEvent(QMouseEvent *event)
        {
        qDebug()<<event;
        }
    
        bool  eventFilter(QObject *obj, QEvent *event)
        {
        if( (dynamic_cast<QMouseEvent*>(event)) && (obj==this))
            qDebug()<<event<<obj;
    
        return false;
        }
    
    };
    

    In the output panel I see:

    QMouseEvent(MouseMove, localPos=102,9, screenPos=744.082,320.039) QLineEdit(0x7fff5a830b60)
    QMouseEvent(MouseButtonPress, LeftButton, localPos=102,9, screenPos=744.082,320.039) QLineEdit(0x7fff5a830b60)
    QMouseEvent(MouseButtonRelease, LeftButton, localPos=102,9, screenPos=744.082,320.039) QLineEdit(0x7fff5a830b60)
    QMouseEvent(MouseButtonDblClick, LeftButton, localPos=102,9, screenPos=744.082,320.039) QLineEdit(0x7fff5a830b60)
    QMouseEvent(MouseButtonDblClick, LeftButton, localPos=102,9, screenPos=744.082,320.039)
    QMouseEvent(MouseButtonRelease, LeftButton, localPos=102,9, screenPos=744.082,320.039) QLineEdit(0x7fff5a830b60)
    

    There are two double click event one with no obj displayed (should be MyLineEdit)
    Don't know why ...

    Silly me, it is the QDebug message in mouseDoubleClickEvent :)


  • Lifetime Qt Champion

    Hi,

    Why are you installing an event filter on the widget since you are overloading the mouseDoubleClickEvent method ?



  • Sgaist...is that question to me or mpergand on his example?

    I'm still lost...not getting the information I need.

    So there isn't an easier way to capture a doubleclick event on a QLineEdit widget than doing an event filter?

    If my widget were a qPushButton called processButton, I could capture it using...

    void DeptScheduling::on_processButton_clicked()
    {
    }

    There isn't just something like that to capture the doubleclick event on a qLineEdit widget?



  • Let's take a concrete example:

    have the user double-click onto a date field and have the date replaced with todays date.

    void mouseDoubleClickEvent(QMouseEvent *event)
       {
       //qDebug()<<event;
       setText(QDate::currentDate().toString());
       QLineEdit::mouseDoubleClickEvent(event);
       }
    

    If you want to do this process outside the QLineEdit subclass, you have to emit a signal instead:

    void mouseDoubleClickEvent(QMouseEvent *event)
       {
       //qDebug()<<event;
       emit doubleClicked();
       QLineEdit::mouseDoubleClickEvent(event);
       }
    

    Look at the doc to know how to define a signal and emit/receive it.



  • Ok...I think this is where the disconnect is.

    Is that a system wide change that would do that for all date fields in your app? Anytime I capture events, I do it on a field by field basis in the cpp of the form I'm working on.

    Like in my example above:

    void DeptScheduling::on_processButton_clicked()
    {
    }

    Within my CPP called DeptScheduling, I have a field called processButton and the above is how I'd control what happens when the user clicks that button.

    I want to control what happens on a double click on several different QLineEdit fields on a particular form, and each one will do something different. When the user double clicks a field called partReserve, I want to run a report showing all the parts in what we call "reserve'. If they doubleclick on a field called onHand, I might want to display a screen that show where all the lots and locations that total that onHand quantity.

    The example you just provided seems to be system wide?



  • In the case of a form, you simply identify the field by its name:
    ui->field1
    ui->filed2
    etc

    in your slot you can do:

    void doubleClickOnField()
    {
    QObject* obj=sender();
    
    if(obj==ui->field1) { }
    else if(obj==ui->field2 {}
    ... etc
    }
    

    Also, you will need to do a cast to retreive the particular object data. For ex:

    QLineEdit* edit=qobject_cast<QLineEdit*>(sender());
    
    if(edit !=nullptr) // beware could be null
    {
    QString text=edit.tex();
    }
    

  • Lifetime Qt Champion

    Not trying to undermine your efforts but I think your users are going to be pretty surprised.

    Personally, I don't expect anything other than text selection when I double click on a line edit type widget.

    If a report shall be generate, I would rather have an explicit button for that.


Log in to reply