c++ 按下鼠标右键时,在QWidget中接受鼠标输入

odopli94  于 2023-03-09  发布在  其他
关注(0)|答案(1)|浏览(213)

我的使用案例如下:我正在开发一个简单的绘图应用程序,其中一个“创新”是隐藏工具面板,直到用户按住鼠标右键,包含工具的窗口才会显示出来。用户再次放开鼠标右键,工具面板就会消失。
这在Qt 6中实现起来相当简单,如下所示:

void MyDrawView::toggleContextMenu(bool show, const QPointF &pos){
    const auto rect=contextMenu->geometry();
    if(show){
        contextMenu->setScreen(this->screen());
        contextMenu->setFocusPolicy( Qt::StrongFocus );
        contextMenu->setFocus( Qt::PopupFocusReason );
        contextMenu->setGeometry(pos.x() - rect.width()/2, pos.y()+10, rect.width(), rect.height());
        contextMenu->show();
    }else{
        contextMenu->hide();
        setFocusPolicy( Qt::StrongFocus );
        setFocus( Qt::PopupFocusReason );
    }
}

void SpaceViewWidget::mousePressEvent(QMouseEvent *event){
    if(Qt::RightButton == event->button()){
        rightPressed=true;
        toggleContextMenu(true, event->globalPosition());
        event->accept();
    }
    else{
        QWidget::mousePressEvent(event);
    }
}

void SpaceViewWidget::mouseReleaseEvent(QMouseEvent *event){
    if(Qt::RightButton == event->button()){
        rightPressed=false;
        toggleContextMenu(false);
        contextMenu->hide(); // <--- IF I COMMENT THIS IT WORKS AFTER RIGHT BUTTON IS RELEASED
        event->accept();
    }
    else{
        QWidget::mousePressEvent(event);
    }
}

然而现在棘手的部分来了。当调色板小部件(contextMenu)显示在它自己的窗口中时,它不接受任何鼠标输入。也就是说,如果我试图点击任何按钮/或拖动任何滑块,它会忽略所有鼠标输入。
如果我在释放鼠标时不隐藏窗口,那么一旦我释放右键,窗口就会像正常一样接受鼠标输入。
所以我的问题是,* 我如何才能诱使QWidget事件系统在新显示的窗口中接受鼠标左键点击,同时一直按下鼠标右键 *?

6l7fqoea

6l7fqoea1#

如果正确地理解了您的需求,那么我可能会为您提供一个变通方案,因为我对MouseEvents的了解还不够,无法准确地找出您的需求。
我所做的是使用您的代码检测mousepressEvent,并修改else语句,LeftButton events将被过滤到其中。
我使用了这些events positions,并将它们与浮动小部件上的objects positions进行了比较,如果碰巧点击了它们,我会触发它们的信号、插槽,或者根据点击的项目修改它们。
这不是一个很好的解决方法,因为它需要你重写并弄清楚如何操纵每个对象(你可以看到我改变滑块值的方式,它不是很方便或有效),但它是有效的,所以它可能会有所帮助。
例如QPushButton,如果mouseevent's position恰好在按钮内部,我调用on_pushButton_Clicked(),这使得它好像在按下右按钮时接受了左按钮mousevent。
下面是修改后的mousepressEvent函数,以及一个关于如何编程(?)按下对象的函数示例。

void Widget::mousePressEvent(QMouseEvent *event)
{
    if(Qt::RightButton == event->button()){
        rightPressed=true;
        toggleContextMenu(true, event->globalPos());
        event->accept();
    }
    else{
        item_clicked(event);
        QWidget::mousePressEvent(event);
    }
}

void Widget::item_clicked(QMouseEvent *event)
{
    int button_x=ui->pushButton->pos().x()+ui->contextMenu->pos().x()+ui->pushButton->width();
    int button_y=ui->pushButton->pos().y()+ui->contextMenu->pos().y()+ui->pushButton->height();

    int slider_x=ui->hslider->pos().x()+ui->contextMenu->pos().x()+ui->hslider->width();
    int slider_y=ui->hslider->pos().y()+ui->contextMenu->pos().y()+ui->hslider->height();

    if(event->pos().x()<=button_x && event->pos().y()<=button_y)
        if(event->pos().x()>=ui->pushButton->pos().x()+ui->contextMenu->pos().x() && event->pos().y()>=ui->pushButton->pos().y()+ui->contextMenu->pos().y())
            on_pushButton_clicked();

    if(event->pos().x()<=slider_x && event->pos().y()<=slider_y)
    {
        if(event->pos().x()>=ui->hslider->pos().x()+ui->contextMenu->pos().x() && event->pos().y()>=ui->hslider->pos().y()+ui->contextMenu->pos().y())
        {
            int slider_val=event->pos().x()-ui->contextMenu->pos().x()-ui->hslider->pos().x();
            ui->hslider->setValue(slider_val);
        }
    }
}

如果你有任何问题或建议,我愿意进一步研究,这很有趣。
我忘了提到我使用的是Qt5setScreen()在我这边是不可用的,以防万一您在使用此代码时遇到一些问题,请记住兼容性

相关问题