QWidget如何在子小部件中接收keyPressEvent

Posted

技术标签:

【中文标题】QWidget如何在子小部件中接收keyPressEvent【英文标题】:QWidget how to receive keyPressEvent inside child widgets 【发布时间】:2014-10-14 19:20:12 【问题描述】:

我有一个主要的Widget,在这个主要的小部件中我有QListWidget 和两个按钮。我已经覆盖了主小部件内的keyPressEvent(继承自QWidget)。当焦点不在QListWidget 上时,我可以接收keyPress 事件,但是当焦点在QListWidget 内时,我无法接收这些keyPress 事件。以下是我用来实现此目的的代码:

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);

【问题讨论】:

你想对按键做什么? 【参考方案1】:

在标题中:

protected:

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

在构造函数中:

qApp->installEventFilter(this);

过滤器:

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);

使用此事件过滤器,您可以捕获所有按键事件并检查谁是发出事件 (obj)

例如:

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

根据您的评论:

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);

【讨论】:

为什么我不能使用 ui->listWidget->installEventFilter(this) 或 this->installEventFilter(this)。我尝试了这两个,但它们不起作用。我想知道为什么? @gmuhammad 您应该将过滤器安装到 qApp。在这种情况下,所有 qApp 事件都将由您的 mainWindow 处理。如果您只想为 listWidget 安装过滤器,您应该创建另一个 QObject 子类并将此子类作为事件过滤器安装到您的小部件。有很多例子如何做到这一点,但在这种情况下,你应该提供一些允许你与你的主窗口进行通信的东西(如果你想在你的主窗口中使用这个事件)但是在我的回答中使用 eventFilter,你不应该子类化一些东西并编写之间的通信2班。它可以工作了 我只想在 listWidget 上处理 KeyPress 事件,或者您可以说一些特定的小部件。假设该列表包含文件名或图像名称。因此,当用户选择某个特定的图像/文件时,我将在另一个小部件中显示图像/文件的详细信息。虽然选择更改事件就足够了,但如果用户从上/下键中选择某些项目,则不会调用选择更改。希望你能理解我的意思。 @gmuhammad 我明白了。请看我的编辑。它可以做你想做的事。【参考方案2】:

您需要使用event filters。

有时对象需要查看并可能拦截 传递给另一个对象的事件。例如,对话框 通常希望过滤某些小部件的按键;例如,到 修改回车键处理。

QObject::installEventFilter() 函数通过设置 一个事件过滤器,导致指定的过滤器对象接收 目标对象在其 QObject::eventFilter() 函数中的事件。一个 事件过滤器在目标对象之前处理事件, 允许它根据需要检查和丢弃事件。一个现有的 可以使用 QObject::removeEventFilter() 删除事件过滤器 功能。

【讨论】:

以上是关于QWidget如何在子小部件中接收keyPressEvent的主要内容,如果未能解决你的问题,请参考以下文章

在子小部件中,如何在 kivy 中获取父小部件的实例

如何将父小部件焦点重定向到子小部件?

Qt5 paintEvent 传播到子小部件

如何从另一个 Qwidget 中删除小部件?

如何在 Flutter 中正确重用 Provider

如何向父 QWidget 添加滚动条