QMainWindow не получает keyPressEvent даже с фильтром событий

Я пытаюсь разработать приложение для просмотра изображений, в котором я использую QGraphicsView для отображения своих изображений. Я хочу, чтобы пользователь мог использовать клавиши со стрелками для открытия следующего/предыдущего изображения, но мой QGraphicsView всегда использует мой keyPressEvent. Я бы хотел, чтобы эти события обрабатывались моим классом QMainWindow. Я понимаю, что это распространенная проблема, и, по-видимому, я могу решить ее, установив фильтр событий и/или убедившись, что мой QMainWindow может иметь фокус. Я сделал и то, и другое, но пока единственное, что я сделал, это не позволить QGraphicsView получить событие, но оно все еще не распространяется на QMainWindow. До сих пор я реализовал метод eventFilter в своем классе QMainWindow и установил его на свой объект QGraphicsView.

Класс QMainWindow

IVMainWindow::IVMainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    setWindowTitle("ImageViewer++");
    setFocusPolicy(Qt::StrongFocus);  // Enabled the QMainWindow to get focus

    m_image_widget = new IVImageWidget();
    m_image_widget->installEventFilter(this);  // Install event filter on QGraphicsView
    setCentralWidget(m_image_widget);

    resize(QGuiApplication::primaryScreen()->availableSize() * 3 / 5);

    // For DEBUG purpose
    loadImage("res/image.png");

    createMenuBar();
    createToolBar();
}

/**
 * Filters out arrow key presses.
 */
bool IVMainWindow::eventFilter(QObject *obj, QEvent *event) {
    if (event->type() == QEvent::KeyPress) {
        auto *keyEvent = static_cast<QKeyEvent *>(event);
        int key = keyEvent->key();
        // Return true to reject the key-presses
        return (key == Qt::Key_Left || key == Qt::Key_Right || key == Qt::Key_Up || key == Qt::Key_Down);
    } else {
        // standard event processing
        return QMainWindow::eventFilter(obj, event);
    }
}

//Never gets to this point, unless I explicitly give it focus by clicking on some other widget than the QGraphicsView...
void IVMainWindow::keyPressEvent(QKeyEvent *event) {
    if (event->key() == Qt::RightArrow) {
        m_logger.Debug("Right arrow pressed.");
    } else if (event->key() == Qt::LeftArrow) {
        m_logger.Debug("Left arrow pressed.");
    }
}

person Zorobay    schedule 31.07.2020    source источник
comment
Ваш вопрос совпадает с этим? (Я знаю, что это для Qt4.)   -  person JarMan    schedule 31.07.2020
comment
@JarMan не уверен. Я попытался установить фильтр событий на область просмотра и на setFocusProxy(0), но ничего не получилось.   -  person Zorobay    schedule 31.07.2020


Ответы (1)


Вам нужно обработать событие в фильтре событий, нормально вызывать QMainWindow::eventFilter для здравомыслия, но он не обрабатывает событие как входящее событие, поэтому обработчики событий не будут вызываться.

bool IVMainWindow::eventFilter(QObject *obj, QEvent *event) {
    if (event->type() == QEvent::KeyPress) {
        auto *keyEvent = static_cast<QKeyEvent *>(event);
        int key = keyEvent->key();
        // Return true to reject the key-presses
        if  (key == Qt::Key_Left || key == Qt::Key_Right || key == Qt::Key_Up || key == Qt::Key_Down)
        {
            //process event here somehow, or instruct your class to do it later
            return true; //filter the event
        }
    } else {
        // standard event processing
        return QMainWindow::eventFilter(obj, event);
    }
}

//This will only be called for the 'real' events, the ones that eventually are received by the main window
void IVMainWindow::keyPressEvent(QKeyEvent *event) {
    if (event->key() == Qt::RightArrow) {
        m_logger.Debug("Right arrow pressed.");
    } else if (event->key() == Qt::LeftArrow) {
        m_logger.Debug("Left arrow pressed.");
    }
}
person Pablo Yaggi    schedule 31.07.2020
comment
Хм, да, спасибо, это работает! Я думал, что смогу перенаправить событие, но явный вызов метода keyPressEvent тоже работает. - person Zorobay; 31.07.2020