QWidget how to receive keyPressEvent inside child widgets
Asked Answered
A

2

6

I have one main Widget and inside this main widget I have QListWidget and two buttons. I have override the keyPressEvent inside the main widget (inherited from QWidget). I can receive the keyPress events when focus is not on QListWidget, but when focus is inside the QListWidget I am unable to receive these keyPress events. Below is the code I have used to achieve this:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    this->setFocusPolicy(Qt::StrongFocus);

    ui->listWidget->addItem(new QListWidgetItem("Item1"));
    ui->listWidget->addItem(new QListWidgetItem("Item2"));
    ui->listWidget->addItem(new QListWidgetItem("Item3"));

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::keyPressEvent(QKeyEvent *event)
{
    qDebug() << "event->key(): " << event->key();

    QWidget::keyPressEvent(event);
}
Apparatus answered 14/10, 2014 at 19:20 Comment(1)
What do you want to do with the key presses?Immerge
N
14

In header:

protected:

     bool eventFilter(QObject *obj, QEvent *event);

In constructor:

qApp->installEventFilter(this);

Filter:

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{   
    if (event->type() == QEvent::KeyPress)
    {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
           qDebug() << "key " << keyEvent->key() << "from" << obj; 
    }
    return QObject::eventFilter(obj, event);
}

With this event filter you can catch all key press events and check who is emit event (obj)

For example:

if ( obj == ui->listWidget )
//event from QListWidget

Accordingly to your comment:

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{ 
    if (event->type() == QEvent::KeyPress)
    {
        if(obj == ui->listWidget)
        {
            QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
            if(keyEvent->key() == Qt::Key_Up)
                qDebug() << "Up";
            if(keyEvent->key() == Qt::Key_Down)
                qDebug() << "Down";
        }
    }
    return QObject::eventFilter(obj, event);
}
Numinous answered 14/10, 2014 at 19:34 Comment(4)
Why can't I use ui->listWidget->installEventFilter(this) or this->installEventFilter(this). I tried these two but they are not working. I wonder why ?Apparatus
@Apparatus You should install filter to qApp. In this case all qApp events will be processed by your mainWindow. If you want install filter only for listWidget you should create another QObject subclass and install this subclass as event filter to your widget. There are many examples how to do it, but in this case you should provide something which allows you communicate with your mainWindow(if you want use this event in your mainWindow) But with eventFilter in my answer you should not subclass something and write communication between 2 classes. It is ready to workNuminous
I just want to handle KeyPress events only on listWidget or you can say some specific widget. Lets say that list contains filenames or image names. So when user selects some particular image/file I'll display the details of image/file in another widget. Though selection change event is sufficient but selection change do not call in case user selects some item from up/down keys. I hope you understand my point.Apparatus
@Apparatus I understood. See my edit please. It can do exactly what you want.Numinous
E
3

You need to use event filters.

Sometimes an object needs to look at, and possibly intercept, the events that are delivered to another object. For example, dialogs commonly want to filter key presses for some widgets; for example, to modify Return-key handling.

The QObject::installEventFilter() function enables this by setting up an event filter, causing a nominated filter object to receive the events for a target object in its QObject::eventFilter() function. An event filter gets to process events before the target object does, allowing it to inspect and discard the events as required. An existing event filter can be removed using the QObject::removeEventFilter() function.

Enneastyle answered 14/10, 2014 at 19:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.