【问题标题】:Transfer mouse events on the masked region of a QWidget to it's parent将 QWidget 的屏蔽区域上的鼠标事件传输到它的父级
【发布时间】:2014-11-06 06:54:22
【问题描述】:

我有一个QMainWindow,其中包含一个循环QWidget。为了有一个圆形的QWidget,我正在使用QWidget::setMask。应用程序在鼠标按下时的预期行为是在 MainWindow 内,这取决于按下鼠标的区域。

class MyMainWindow: public QMainWindow
{
public:
    MyMainWindow():QMainWindow()
    {

    }
    void mousePressEvent( QMouseEvent * event )
    {
        qDebug()<<"Clicked on MainWindow";
    }
};

class CircularWidget: public QWidget
{
public:
    CircularWidget( QWidget * parent ):QWidget( parent )
    {

    }
    void paintEvent(QPaintEvent * event)
    {
        QRegion circularMask( QRect( pos(), size() ), QRegion::Ellipse );
        setMask( circularMask );
        setStyleSheet("background-color:black;");
        QWidget::paintEvent( event );
    }
    void mousePressEvent( QMouseEvent * event )
    {
        qDebug()<<"Clicked on Circular Widget";
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QMainWindow w;
    w.resize( 400, 400 );

    CircularWidget circularWidget( &w );
    circularWidget.show();

    w.setCentralWidget( &circularWidget );
    w.show();
    return a.exec();
}

目前,当我在圆形区域内单击时,我会在我的小部件中收到该事件。但是圈外的所有鼠标按下事件都丢失了。我在 Qt 文档中看到:Masked widgets receive mouse events only on their visible portions。有没有办法将其他鼠标点击事件(图中灰色区域的事件)传递给父widget?

【问题讨论】:

  • 那么 CircularWidget 覆盖了整个主窗口?你如何把这个小部件放在主窗口中?
  • 我将不得不调整它的大小,但目前它覆盖了整个主窗口。我只想让主窗口占用圆圈外的所有鼠标事件

标签: c++ qt qwidget masking


【解决方案1】:

您没有在 MyMainWindow 类中获得鼠标事件的原因是因为在您的 main() 函数中,您创建了 QMainWindow 类的主窗口对象。 为了处理圆形小部件上的鼠标单击事件,我将在此处使用信号/插槽机制。 IE。让圆形小部件在每次单击时发出一个信号。任何其他接收者都会将其视为自己的。例如:

class MyMainWindow: public QMainWindow
{
    Q_OBJECT
    [..]
public slots:
    void handleMouseClick(const QPoint &) {}
};

class CircularWidget: public QWidget
{
    Q_OBJECT
public:
    [..]
    void mousePressEvent( QMouseEvent * event )
    { emit mouseClicked(event->pos()); }
signals:
    void mouseClicked(const QPoint &);
};

最后建立连接。在MyMainWindow 类中,您将能够处理来自圆形小部件和主窗口本身的鼠标单击事件。

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyMainWindow w; // <-------- This should be MyMainWindow instead of QMainWindow

    CircularWidget circularWidget( &w ); 
    w.setCentralWidget( &circularWidget );

    QObject::connect(&circularWidget, SIGNAL(mouseClicked(const QPoint &)),
                     &w, SLOT(handleMouseClick(const QPoint &));

    return a.exec();
}

【讨论】:

  • 但是当我点击圆形遮罩外的区域时,并没有调用圆形小部件的 mousepressevent。而且它也没有调用 mainWindow 的 mousepressEvent
  • @sajas,请查看我的更新回复。问题是您创建了 QMainWindow 对象而不是创建 MyMainWindow 类对象。
  • 糟糕。错过了。谢谢。
【解决方案2】:

如果指针在区域之外,正确的解决方案是拒绝鼠标按下事件,因此或多或少应该如下所示:

void mousePressEvent( QMouseEvent * event )
{
    QRegion circularMask( QRect( pos(), size() ), QRegion::Ellipse ); // it would be nice to make it a class field

    if (!circularMask.contains(event->pos()) {
        event->ignore();
    }
}

documentation:

鼠标事件包含一个特殊的接受标志,指示是否 接收者想要这个事件。如果鼠标,你应该调用 ignore() 您的小部件不处理事件。鼠标事件向上传播 父小部件链,直到小部件使用 accept() 接受它,或者 事件过滤器消耗它。

【讨论】:

    猜你喜欢
    • 2018-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-07
    • 1970-01-01
    • 2020-03-21
    相关资源
    最近更新 更多